bool IMyShipController.TryGetPlanetElevation(MyPlanetElevation detail, out double elevation)
        {
            var blockPosition = this.PositionComp.GetPosition();

            if (!MyGravityProviderSystem.IsPositionInNaturalGravity(blockPosition))
            {
                elevation = double.PositiveInfinity;
                return(false);
            }
            var boundingBox   = PositionComp.WorldAABB;
            var nearestPlanet = MyGamePruningStructure.GetClosestPlanet(ref boundingBox);

            if (nearestPlanet == null)
            {
                elevation = double.PositiveInfinity;
                return(false);
            }

            switch (detail)
            {
            case MyPlanetElevation.Sealevel:
                elevation = ((boundingBox.Center - nearestPlanet.PositionComp.GetPosition()).Length() - nearestPlanet.AverageRadius);
                return(true);

            case MyPlanetElevation.Surface:
                var      controlledEntityPosition = CubeGrid.Physics.CenterOfMassWorld;
                Vector3D closestPoint             = nearestPlanet.GetClosestSurfacePointGlobal(ref controlledEntityPosition);
                elevation = Vector3D.Distance(closestPoint, controlledEntityPosition);
                return(true);

            default:
                throw new ArgumentOutOfRangeException("detail", detail, null);
            }
        }
        /// <summary>
        /// Calculate propper direction for meteorits. Everytime above horizon.
        /// </summary>
        /// <param name="direction"></param>
        /// <returns></returns>
        private static Vector3 GetCorrectedDirection(Vector3 direction)
        {
            var currDir = direction;

            if (m_currentTarget == null)
            {
                return(currDir);
            }

            var tgtPos = m_currentTarget.Value.Center;

            MyMeteorShower.m_tgtPos = tgtPos;

            if (!MyGravityProviderSystem.IsPositionInNaturalGravity(tgtPos))
            {
                return(currDir);
            }

            var pltTgtDir = -Vector3D.Normalize(MyGravityProviderSystem.CalculateNaturalGravityInPoint(tgtPos));
            var tmpVec    = Vector3D.Normalize(Vector3D.Cross(pltTgtDir, currDir));
            var mirror    = Vector3D.Normalize(Vector3D.Cross(tmpVec, pltTgtDir));

            MyMeteorShower.m_mirrorDir = mirror;
            MyMeteorShower.m_pltTgtDir = pltTgtDir;
            MyMeteorShower.m_normalSun = tmpVec;

            double horizonRatio = pltTgtDir.Dot(currDir);

            //below down horizon
            if (horizonRatio < -HORIZON_ANGLE_FROM_ZENITH_RATIO)
            {
                return(Vector3D.Reflect(-currDir, mirror));
            }

            // between below and above horizon (prohi
            if (horizonRatio < HORIZON_ANGLE_FROM_ZENITH_RATIO)
            {
                MatrixD tmpMat = MatrixD.CreateFromAxisAngle(tmpVec, -Math.Asin(HORIZON_ANGLE_FROM_ZENITH_RATIO));
                return(Vector3D.Transform(mirror, tmpMat));
            }

            // above 20 Degree above horizon
            return(currDir);
        }
        bool IMyShipController.TryGetPlanetPosition(out Vector3D position)
        {
            var blockPosition = this.PositionComp.GetPosition();

            if (!MyGravityProviderSystem.IsPositionInNaturalGravity(blockPosition))
            {
                position = Vector3D.Zero;
                return(false);
            }
            var boundingBox   = PositionComp.WorldAABB;
            var nearestPlanet = MyGamePruningStructure.GetClosestPlanet(ref boundingBox);

            if (nearestPlanet == null)
            {
                position = Vector3D.Zero;
                return(false);
            }
            position = nearestPlanet.PositionComp.GetPosition();
            return(true);
        }
Example #4
0
 public override void Draw()
 {
     base.Draw();
     if (MyDebugDrawSettings.DEBUG_DRAW_METEORITS_DIRECTIONS)
     {
         Vector3D m_currDir = GetCorrectedDirection(MySector.DirectionToSunNormalized);
         MyRenderProxy.DebugDrawLine3D(m_tgtPos, m_tgtPos + 10 * MySector.DirectionToSunNormalized, Color.Yellow, Color.Yellow, false);
         MyRenderProxy.DebugDrawText3D(m_tgtPos + 10 * MySector.DirectionToSunNormalized, "Sun direction (sd)", Color.Yellow, 0.5F, false, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_BOTTOM);
         MyRenderProxy.DebugDrawLine3D(m_tgtPos, m_tgtPos + 10 * m_currDir, Color.Red, Color.Red, false);
         MyRenderProxy.DebugDrawText3D(m_tgtPos + 10 * m_currDir, "Current meteorits direction (cd)", Color.Red, 0.5F, false, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_TOP);
         if (MyGravityProviderSystem.IsPositionInNaturalGravity(m_tgtPos))
         {
             MyRenderProxy.DebugDrawLine3D(m_tgtPos, m_tgtPos + 10 * m_normalSun, Color.Blue, Color.Blue, false);
             MyRenderProxy.DebugDrawText3D(m_tgtPos + 10 * m_normalSun, "Perpendicular to sd and n0 ", Color.Blue, 0.5F, false, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_CENTER);
             MyRenderProxy.DebugDrawLine3D(m_tgtPos, m_tgtPos + 10 * m_pltTgtDir, Color.Green, Color.Green, false);
             MyRenderProxy.DebugDrawText3D(m_tgtPos + 10 * m_pltTgtDir, "Dir from center of planet to target (n0)", Color.Green, 0.5F, false, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_CENTER);
             MyRenderProxy.DebugDrawLine3D(m_tgtPos, m_tgtPos + 10 * m_mirrorDir, Color.Purple, Color.Purple, false);
             MyRenderProxy.DebugDrawText3D(m_tgtPos + 10 * m_mirrorDir, "Horizon in plane n0 and sd (ho)", Color.Purple, 0.5F, false, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_CENTER);
         }
     }
 }
        private bool SpawnDrone(MyRadioAntenna antenna, long ownerId, Vector3D position, MySpawnGroupDefinition spawnGroup, Vector3?spawnUp = null, Vector3?spawnForward = null)
        {
            long     antennaEntityId = antenna.EntityId;
            Vector3D antennaPos      = antenna.PositionComp.GetPosition();

            Vector3D upVector;

            var planet = MyGamePruningStructure.GetClosestPlanet(position);

            if (planet != null)
            {
                if (!MyGravityProviderSystem.IsPositionInNaturalGravity(antennaPos))
                {
                    MySandboxGame.Log.WriteLine("Couldn't spawn drone; antenna is not in natural gravity but spawn location is.");
                    return(false);
                }
                planet.CorrectSpawnLocation(ref position, spawnGroup.SpawnRadius * 2.0);
                upVector = position - planet.PositionComp.GetPosition();
                upVector.Normalize();
            }
            else
            {
                var totalGravityInPoint = MyGravityProviderSystem.CalculateTotalGravityInPoint(position);
                if (totalGravityInPoint != Vector3.Zero)
                {
                    upVector = -totalGravityInPoint;
                    upVector.Normalize();
                }
                else if (spawnUp != null)
                {
                    upVector = spawnUp.Value;
                }
                else
                {
                    upVector = MyUtils.GetRandomVector3Normalized();
                }
            }

            Vector3D direction = MyUtils.GetRandomPerpendicularVector(ref upVector);

            if (spawnForward != null)
            {
                // Align forward to up vector.
                Vector3 forward = spawnForward.Value;
                if (Math.Abs(Vector3.Dot(forward, upVector)) >= 0.98f)
                {
                    forward = Vector3.CalculatePerpendicularVector(upVector);
                }
                else
                {
                    Vector3 right = Vector3.Cross(forward, upVector);
                    right.Normalize();
                    forward = Vector3.Cross(upVector, right);
                    forward.Normalize();
                }

                direction = forward;
            }

            MatrixD originMatrix = MatrixD.CreateWorld(position, direction, upVector);

            foreach (var shipPrefab in spawnGroup.Prefabs)
            {
                Vector3D shipPosition = Vector3D.Transform((Vector3D)shipPrefab.Position, originMatrix);

                List <MyCubeGrid> tmpGridList = new List <MyCubeGrid>();

                Stack <Action> callback = new Stack <Action>();
                callback.Push(delegate() { ChangeDroneOwnership(tmpGridList, ownerId, antennaEntityId); });

                MyPrefabManager.Static.SpawnPrefab(
                    resultList: tmpGridList,
                    prefabName: shipPrefab.SubtypeId,
                    position: shipPosition,
                    forward: direction,
                    up: upVector,
                    initialLinearVelocity: default(Vector3),
                    beaconName: null,
                    spawningOptions: VRage.Game.ModAPI.SpawningOptions.None,
                    ownerId: ownerId,
                    updateSync: true, callbacks: callback);
            }
            return(true);
        }
        private bool SpawnDrone(MyRadioAntenna antenna, long ownerId, Vector3D position, MySpawnGroupDefinition spawnGroup)
        {
            long     antennaEntityId = antenna.EntityId;
            Vector3D antennaPos      = antenna.PositionComp.GetPosition();

            var planet = MyGravityProviderSystem.GetStrongestGravityWell(position);

            Vector3D upVector;

            if (planet != null && planet.IsPositionInGravityWell(position))
            {
                if (!MyGravityProviderSystem.IsPositionInNaturalGravity(antennaPos))
                {
                    MySandboxGame.Log.WriteLine("Couldn't spawn drone; antenna is not in natural gravity but spawn location is.");
                    return(false);
                }
                planet.CorrectSpawnLocation(ref position, spawnGroup.SpawnRadius * 2.0);
                upVector = -planet.GetWorldGravityNormalized(ref position);
            }
            else
            {
                upVector = MyUtils.GetRandomVector3Normalized();
            }

            Vector3D direction    = MyUtils.GetRandomPerpendicularVector(ref upVector);
            MatrixD  originMatrix = MatrixD.CreateWorld(position, direction, upVector);

            foreach (var shipPrefab in spawnGroup.Prefabs)
            {
                Vector3D shipPosition = Vector3D.Transform((Vector3D)shipPrefab.Position, originMatrix);

                m_tmpGridList.Clear();

                MyPrefabManager.Static.SpawnPrefab(
                    resultList: m_tmpGridList,
                    prefabName: shipPrefab.SubtypeId,
                    position: shipPosition,
                    forward: direction,
                    up: upVector,
                    initialLinearVelocity: default(Vector3),
                    beaconName: null,
                    spawningOptions: VRage.Game.ModAPI.SpawningOptions.None,
                    ownerId: ownerId,
                    updateSync: true);

                foreach (var grid in m_tmpGridList)
                {
                    grid.ChangeGridOwnership(ownerId, MyOwnershipShareModeEnum.None);

                    MyRemoteControl firstRemote = null;

                    foreach (var block in grid.CubeBlocks)
                    {
                        if (block.FatBlock == null)
                        {
                            continue;
                        }

                        var pb = block.FatBlock as MyProgrammableBlock;
                        if (pb != null)
                        {
                            pb.SendRecompile();
                        }

                        var remote = block.FatBlock as MyRemoteControl;
                        if (firstRemote == null)
                        {
                            firstRemote = remote;
                        }
                    }

                    // If there's no remote control on the grid, we have to register it as is
                    RegisterDrone(antennaEntityId, (MyEntity)firstRemote ?? (MyEntity)grid);
                }

                m_tmpGridList.Clear();
            }
            return(true);
        }
Example #7
0
        public void BuyGrid(int number)
        {
            if (!list.items.ContainsKey(number))
            {
                Context.Respond("There is no item in the market for that slot number.");
                confirmations.Remove(Context.Player.IdentityId);
                return;
            }
            MarketItem item = list.items[number];

            if (!File.Exists(AlliancePlugin.path + "//ShipMarket//ForSale//" + item.ItemId + ".json"))
            {
                Context.Respond("That grid is no longer available for sale.");
                confirmations.Remove(Context.Player.IdentityId);
                return;
            }
            if (!File.Exists(AlliancePlugin.path + "//ShipMarket//Grids//" + item.ItemId + ".xml"))
            {
                Context.Respond("This grid should be available, but its file for the grid doesnt exist.");
                confirmations.Remove(Context.Player.IdentityId);
                return;
            }
            if (MyGravityProviderSystem.IsPositionInNaturalGravity(Context.Player.GetPosition()))
            {
                Context.Respond("You cannot use this command in natural gravity!");
                confirmations.Remove(Context.Player.IdentityId);
                return;
            }

            foreach (DeniedLocation denied in AlliancePlugin.HangarDeniedLocations)
            {
                if (Vector3.Distance(Context.Player.GetPosition(), new Vector3(denied.x, denied.y, denied.z)) <= denied.radius)
                {
                    Context.Respond("Cannot buy here, too close to a denied location.");
                    confirmations.Remove(Context.Player.IdentityId);
                    return;
                }
            }
            if (EconUtils.getBalance(Context.Player.IdentityId) >= item.Price)
            {
                if (confirmations.ContainsKey(Context.Player.IdentityId))
                {
                    if (confirmations[Context.Player.IdentityId] >= DateTime.Now)
                    {
                        if (GridManager.LoadGrid(AlliancePlugin.path + "//ShipMarket//Grids//" + item.ItemId + ".xml", Context.Player.GetPosition(), false, Context.Player.SteamUserId, item.Name))
                        {
                            EconUtils.takeMoney(Context.Player.IdentityId, item.Price);
                            long sellerId = MySession.Static.Players.TryGetIdentityId(item.SellerSteamId);
                            EconUtils.addMoney(sellerId, item.Price);
                            if (AlliancePlugin.GridBackupInstalled)
                            {
                                AlliancePlugin.BackupGridMethod(GridManager.GetObjectBuilders(AlliancePlugin.path + "//ShipMarket//Grids//" + item.ItemId + ".xml"), Context.Player.IdentityId);
                            }
                            item.Buyer  = Context.Player.SteamUserId;
                            item.soldAt = DateTime.Now;
                            item.Status = ItemStatus.Sold;
                            Context.Respond("The grid should appear near you.");
                            confirmations.Remove(Context.Player.IdentityId);
                            if (!Directory.Exists(AlliancePlugin.path + "//ShipMarket//Sold//" + item.SellerSteamId))
                            {
                                Directory.CreateDirectory(AlliancePlugin.path + "//ShipMarket//Sold//" + item.SellerSteamId);
                            }
                            list.items.Remove(number);

                            File.Delete(AlliancePlugin.path + "//ShipMarket//ForSale//" + item.ItemId + ".json");
                            utils.WriteToJsonFile <MarketItem>(AlliancePlugin.path + "//ShipMarket//Sold//" + item.SellerSteamId + "//" + item.ItemId, item);
                        }
                        else
                        {
                            Context.Respond("Failed to load the grid! transaction cancelled.");
                            return;
                        }
                    }
                    else
                    {
                        Context.Respond("Time ran out, start again");
                        confirmations[Context.Player.IdentityId] = DateTime.Now.AddSeconds(20);
                    }
                }
                else
                {
                    Context.Respond("Run command again within 20 seconds to confirm. Target grid name is " + item.Name + " Sold by " + AlliancePlugin.GetPlayerName(item.SellerSteamId));
                    confirmations.Add(Context.Player.IdentityId, DateTime.Now.AddSeconds(20));
                    Context.Respond("It costs " + String.Format("{0:n0}", item.Price) + " SC.");
                }
            }
            else
            {
                Context.Respond("You cannot afford that. It costs " + String.Format("{0:n0}", item.Price) + " SC.");
            }
        }
Example #8
0
        public void EndListing(int number)
        {
            if (!list.items.ContainsKey(number))
            {
                Context.Respond("There is no item in the market for that slot number.");
                return;
            }
            MarketItem item = list.items[number];

            if (!item.SellerSteamId.Equals(Context.Player.SteamUserId))
            {
                Context.Respond("This listing doesnt belong to you.");
                return;
            }
            if (!File.Exists(AlliancePlugin.path + "//ShipMarket//ForSale//" + item.ItemId + ".json"))
            {
                Context.Respond("That grid is no longer available for sale.");
                return;
            }
            if (!File.Exists(AlliancePlugin.path + "//ShipMarket//Grids//" + item.ItemId + ".xml"))
            {
                Context.Respond("This grid should be available, but its file for the grid doesnt exist.");
                return;
            }
            if (MyGravityProviderSystem.IsPositionInNaturalGravity(Context.Player.GetPosition()))
            {
                Context.Respond("You cannot use this command in natural gravity!");
                return;
            }

            foreach (DeniedLocation denied in AlliancePlugin.HangarDeniedLocations)
            {
                if (Vector3.Distance(Context.Player.GetPosition(), new Vector3(denied.x, denied.y, denied.z)) <= denied.radius)
                {
                    Context.Respond("Cannot buy here, too close to a denied location.");
                    return;
                }
            }

            if (GridManager.LoadGrid(AlliancePlugin.path + "//ShipMarket//Grids//" + item.ItemId + ".xml", Context.Player.GetPosition(), true, Context.Player.SteamUserId, item.Name))
            {
                EconUtils.takeMoney(Context.Player.IdentityId, item.Price);
                long sellerId = MySession.Static.Players.TryGetIdentityId(item.SellerSteamId);
                EconUtils.addMoney(sellerId, item.Price);
                if (AlliancePlugin.GridBackupInstalled)
                {
                    AlliancePlugin.BackupGridMethod(GridManager.GetObjectBuilders(AlliancePlugin.path + "//ShipMarket//Grids//" + item.ItemId + ".xml"), Context.Player.IdentityId);
                }
                item.Buyer  = Context.Player.SteamUserId;
                item.soldAt = DateTime.Now;
                if (!Directory.Exists(AlliancePlugin.path + "//ShipMarket//Sold//" + item.SellerSteamId))
                {
                    Directory.CreateDirectory(AlliancePlugin.path + "//ShipMarket//Sold//" + item.SellerSteamId);
                }
                list.items.Remove(number);
                File.Delete(AlliancePlugin.path + "//ShipMarket//ForSale//" + item.ItemId + ".json");
                File.Delete(AlliancePlugin.path + "//ShipMarket//Grids//" + item.ItemId + ".xml");
                Context.Respond("Ended the listing, the grid should appear near you.");
            }
            else
            {
                Context.Respond("Failed to load the grid! transaction cancelled.");
                return;
            }
        }
Example #9
0
        public void Sell(string price, string name)
        {
            if (MyGravityProviderSystem.IsPositionInNaturalGravity(Context.Player.GetPosition()))
            {
                Context.Respond("You cannot use this command in natural gravity!");
                confirmations.Remove(Context.Player.IdentityId);
                return;
            }

            foreach (DeniedLocation denied in AlliancePlugin.HangarDeniedLocations)
            {
                if (Vector3.Distance(Context.Player.GetPosition(), new Vector3(denied.x, denied.y, denied.z)) <= denied.radius)
                {
                    Context.Respond("Cannot sell here, too close to a denied location.");
                    confirmations.Remove(Context.Player.IdentityId);
                    return;
                }
            }
            Int64 amount;

            price = price.Replace(",", "");
            price = price.Replace(".", "");
            price = price.Replace(" ", "");
            try
            {
                amount = Int64.Parse(price);
            }
            catch (Exception)
            {
                Context.Respond("Error parsing amount", Color.Red, "Bank Man");
                return;
            }
            if (amount < 0 || amount == 0)
            {
                Context.Respond("Must be a positive amount", Color.Red, "Bank Man");
                return;
            }
            ConcurrentBag <MyGroups <MyCubeGrid, MyGridMechanicalGroupData> .Group> gridWithSubGrids = GridFinder.FindLookAtGridGroupMechanical(Context.Player.Character);

            List <MyCubeGrid> grids = new List <MyCubeGrid>();


            foreach (var item1 in gridWithSubGrids)
            {
                foreach (MyGroups <MyCubeGrid, MyGridMechanicalGroupData> .Node groupNodes in item1.Nodes)
                {
                    MyCubeGrid grid = groupNodes.NodeData;

                    if (FacUtils.IsOwnerOrFactionOwned(grid, Context.Player.IdentityId, false))
                    {
                        if (!grids.Contains(grid))
                        {
                            foreach (MySurvivalKit block in grid.GetFatBlocks().OfType <MySurvivalKit>())
                            {
                                block.CustomData = "Custom Data was cleared.";
                            }
                            foreach (MyMedicalRoom block in grid.GetFatBlocks().OfType <MyMedicalRoom>())
                            {
                                block.CustomData = "Custom Data was cleared.";
                            }
                            List <MyProgrammableBlock> removeThese = new List <MyProgrammableBlock>();
                            foreach (MyProgrammableBlock block in grid.GetFatBlocks().OfType <MyProgrammableBlock>())
                            {
                                removeThese.Add(block);
                            }
                            foreach (MyProgrammableBlock block in removeThese)
                            {
                                grid.RemoveBlock(block.SlimBlock);
                            }
                            grids.Add(grid);
                        }
                    }
                }
            }
            if (grids.Count == 0)
            {
                Context.Respond("Could not find any grids you own. Are you looking directly at it?");
                return;
            }
            MarketItem item = new MarketItem();

            item.Setup(grids, name, amount, Context.Player.SteamUserId);
            if (list.AddItem(item))
            {
                if (GridManager.SaveGridNoDelete(AlliancePlugin.path + "//ShipMarket//Grids//" + item.ItemId + ".xml", item.ItemId.ToString(), false, false, grids))
                {
                    Context.Respond("Added the item to the market!");

                    utils.WriteToJsonFile <MarketItem>(AlliancePlugin.path + "//ShipMarket//ForSale//" + item.ItemId + ".json", item);
                    foreach (MyCubeGrid grid in grids)
                    {
                        if (grid != null)
                        {
                            grid.Close();
                        }
                    }
                }
            }
            else
            {
                Context.Respond("Failed to add the grid to the market. Try again.");
            }
        }
Example #10
0
        public void transmit()
        {
            foreach (MyPlayer p in MySession.Static.Players.GetOnlinePlayers())
            {
                List <IMyGps> playergpsList = MyAPIGateway.Session?.GPS.GetGpsList(p.Identity.IdentityId);

                if (playergpsList == null)
                {
                    break;
                }

                foreach (IMyGps gps in playergpsList)
                {
                    if (gps.Description.Contains("Cronch"))
                    {
                        MyAPIGateway.Session?.GPS.RemoveGps(p.Identity.IdentityId, gps);
                    }
                }
            }
            foreach (var group in MyCubeGridGroups.Static.Logical.Groups)
            {
                bool NPC = false;
                foreach (var item in group.Nodes)
                {
                    MyCubeGrid grid = item.NodeData;
                    // TransmitPlugin.Log.Info(grid.DisplayName);
                    if (((int)grid.Flags & 4) != 0)
                    {
                        //concealed
                        break;
                    }
                    if (grid.IsStatic && !TransmitPlugin.config.broadcastStations)
                    {
                        break;
                    }
                    if (MyGravityProviderSystem.IsPositionInNaturalGravity(grid.PositionComp.GetPosition()) && !TransmitPlugin.config.broadcastInGravity)
                    {
                        break;
                    }

                    //this bit requires a fac utils to get the faction tag, you can remove it if you dont need it
                    foreach (long l in grid.BigOwners)
                    {
                        if (FacUtils.GetFactionTag(l) != null && FacUtils.GetFactionTag(l).Length > 3)
                        {
                            NPC = true;
                        }
                    }

                    if (NPC)
                    {
                        break;
                    }
                    int PCU = 0;
                    PCU = grid.BlocksPCU;
                    Vector3 location = grid.PositionComp.GetPosition();
                    //get the gps
                    float           broadcastRange = 0;
                    MyGpsCollection gpsCollection  = (MyGpsCollection)MyAPIGateway.Session?.GPS;


                    broadcastRange = grid.BlocksPCU * TransmitPlugin.config.meterPerPCU;


                    if (PCU < TransmitPlugin.config.minimumPCU)
                    {
                        break;
                    }
                    IMyFaction gridOwner = FacUtils.GetPlayersFaction(FacUtils.GetOwner(grid));

                    foreach (MyPlayer p in MySession.Static.Players.GetOnlinePlayers())
                    {
                        List <MyGps> gpsList  = new List <MyGps>();
                        float        distance = Vector3.Distance(location, p.GetPosition());
                        if (distance <= broadcastRange)
                        {
                            MyGps gps;
                            //add a new gps point if player is in range
                            if (gridOwner != null)
                            {
                                if (gridOwner.IsNeutral(p.Identity.IdentityId) || gridOwner.IsFriendly(p.Identity.IdentityId))
                                {
                                    gps = CreateGps(grid, Color.RoyalBlue, 60, broadcastRange);
                                }
                                else
                                {
                                    gps = CreateGps(grid, Color.Red, 60, broadcastRange);
                                }
                            }
                            else
                            {
                                gps = CreateGps(grid, Color.Red, 60, broadcastRange);
                            }

                            gpsList.Add(gps);
                        }
                        foreach (MyGps gps in gpsList)
                        {
                            MyGps gpsRef   = gps;
                            long  entityId = 0L;
                            entityId = gps.EntityId;
                            gpsCollection.SendAddGps(p.Identity.IdentityId, ref gpsRef, entityId, TransmitPlugin.config.soundForGPS);
                        }
                    }
                }
            }
        }
Example #11
0
        public static void SpawnCargoShip(bool checkGravity)
        {
            Init(  );
            Wrapper.GameAction(() =>
            {
                if (ExtenderOptions.IsDebugging)
                {
                    Essentials.Log.Info("Spawn cargo ship");
                }
                // Select a spawn group to spawn
                MySpawnGroupDefinition spawnGroup = PickRandomSpawnGroup( );
                if (spawnGroup == null)
                {
                    return;
                }

                spawnGroup.ReloadPrefabs( );

                double spawnDistance    = NEUTRAL_SHIP_SPAWN_DISTANCE;
                Vector3D playerPosition = Vector3D.Zero;
                bool isWorldLimited     = MyEntities.IsWorldLimited( );
                int numPlayers          = 0;

                if (isWorldLimited)
                {
                    spawnDistance = Math.Min(spawnDistance, MyEntities.WorldSafeHalfExtent( ) - spawnGroup.SpawnRadius);
                }
                else
                {
                    // In infinite worlds players can be thousands of kilometers away, so spawn ship around random player
                    // so cargo ships will be spawned around every player at some time
                    var players = MySession.Static.Players.GetOnlinePlayers( );
                    // In DS there can be no players connected
                    numPlayers = Math.Max(0, players.Count - 1);
                    int randomPlayerPosition = MyUtils.GetRandomInt(0, numPlayers);
                    int i = 0;
                    foreach (var player in players)
                    {
                        if (i == randomPlayerPosition)
                        {
                            if (player.Character != null)
                            {
                                playerPosition = player.GetPosition( );
                            }
                            break;
                        }
                        i++;
                    }
                }

                if (spawnDistance < 0.0f)
                {
                    if (ExtenderOptions.IsDebugging)
                    {
                        Essentials.Log.Info("Not enough space in the world to spawn such a huge spawn group!");
                    }
                    return;
                }

                double forbiddenRadius = NEUTRAL_SHIP_FORBIDDEN_RADIUS;
                BoundingBoxD spawnBox;
                if (isWorldLimited)
                {
                    spawnBox = new BoundingBoxD(new Vector3D(playerPosition - spawnDistance), new Vector3D(playerPosition + spawnDistance));
                }
                else
                {
                    // We need to extend bouding box so cargo ships aren't spawned near other players
                    GetSafeBoundingBoxForPlayers(playerPosition, spawnDistance, out spawnBox);
                    // Forbidden radius is sphere around all players in box.
                    // Bounding box is generated from players positions so their distance to center shall be same for all players
                    forbiddenRadius += spawnBox.HalfExtents.Max( ) - NEUTRAL_SHIP_FORBIDDEN_RADIUS;
                }
                // Get the direction to the center and deviate it randomly
                Vector3D?origin = MyUtils.GetRandomBorderPosition(ref spawnBox);

                origin = MyEntities.FindFreePlace(origin.Value, spawnGroup.SpawnRadius);
                if (!origin.HasValue)
                {
                    if (ExtenderOptions.IsDebugging)
                    {
                        Essentials.Log.Info("Couldn't find free place for cargo spawn");
                    }
                    return;
                }

                // Radius in arc units of the forbidden sphere in the center, when viewed from origin
                float centerArcRadius = (float)Math.Atan(forbiddenRadius / (origin.Value - spawnBox.Center).Length( ));

                // Generate direction with elevation from centerArcRadius radians to (cAR + N_S_D_S) radians
                Vector3D direction = -Vector3D.Normalize(origin.Value);
                float theta        = MyUtils.GetRandomFloat(centerArcRadius, centerArcRadius + NEUTRAL_SHIP_DIRECTION_SPREAD);
                float phi          = MyUtils.GetRandomRadian( );
                Vector3D cosVec    = Vector3D.CalculatePerpendicularVector(direction);
                Vector3D sinVec    = Vector3D.Cross(direction, cosVec);
                cosVec            *= (Math.Sin(theta) * Math.Cos(phi));
                sinVec            *= (Math.Sin(theta) * Math.Sin(phi));
                direction          = direction * Math.Cos(theta) + cosVec + sinVec;

                Vector3D destination = Vector3D.Zero;
                RayD ray             = new RayD(origin.Value, direction);
                double?intersection  = ray.Intersects(spawnBox);
                Vector3D directionMult;
                if (!intersection.HasValue || intersection.Value < NEUTRAL_SHIP_MINIMAL_ROUTE_LENGTH)
                {
                    directionMult = direction * NEUTRAL_SHIP_MINIMAL_ROUTE_LENGTH;
                }
                else
                {
                    directionMult = direction * intersection.Value;
                }
                destination = origin.Value + directionMult;

                Vector3D upVector    = Vector3D.CalculatePerpendicularVector(direction);
                Vector3D rightVector = Vector3D.Cross(direction, upVector);
                MatrixD originMatrix = MatrixD.CreateWorld(origin.Value, direction, upVector);

                // CH:TODO: Convex cast to detect collision
                // Check ships' path to avoid possible collisions. (TODO: But only if it is said in the definitions)
                m_raycastHits.Clear( );
                foreach (var shipPrefab in spawnGroup.Prefabs)
                {
                    var prefabDef = MyDefinitionManager.Static.GetPrefabDefinition(shipPrefab.SubtypeId);
                    Debug.Assert(prefabDef != null);

                    Vector3D shipPosition    = Vector3.Transform(shipPrefab.Position, originMatrix);
                    Vector3D shipDestination = shipPosition + directionMult;
                    float radius             = prefabDef == null ? 10.0f : prefabDef.BoundingSphere.Radius;

                    if (checkGravity)
                    {
                        //these point checks could be done in the trajectory intersect, but checking points is faster than ray intersect
                        if (MyGravityProviderSystem.IsPositionInNaturalGravity(shipPosition, spawnGroup.SpawnRadius))
                        {
                            if (ExtenderOptions.IsDebugging)
                            {
                                Essentials.Log.Info("Failed to spawn cargo ship: Spawn location is in gravity well");
                            }
                            return;
                        }
                        if (MyGravityProviderSystem.IsPositionInNaturalGravity(shipDestination, spawnGroup.SpawnRadius))
                        {
                            if (ExtenderOptions.IsDebugging)
                            {
                                Essentials.Log.Info("Failed to spawn cargo ship: Destination is in gravity well");
                            }
                        }
                        if (MyGravityProviderSystem.DoesTrajectoryIntersectNaturalGravity(shipPosition, shipDestination, spawnGroup.SpawnRadius + 500))
                        {
                            if (ExtenderOptions.IsDebugging)
                            {
                                Essentials.Log.Info("Failed to spawn cargo ship: Ship path intersects gravity well");
                            }
                            return;
                        }
                    }

                    MyPhysics.CastRay(shipPosition, shipDestination, m_raycastHits, MyPhysics.CollisionLayers.ObjectDetectionCollisionLayer);
                    if (m_raycastHits.Count > 0)
                    {
                        if (ExtenderOptions.IsDebugging)
                        {
                            Essentials.Log.Info("Failed to spawn cargo ship: Ship path intersects another object");
                        }
                        return;
                    }

                    for (int i = 0; i < 4; ++i)
                    {
                        Vector3D shiftVector = upVector * m_upVecMultipliers[i] * radius + rightVector * m_rightVecMultipliers[i] * radius;
                        MyPhysics.CastRay(shipPosition + shiftVector, shipDestination + shiftVector, m_raycastHits, MyPhysics.CollisionLayers.ObjectDetectionCollisionLayer);

                        if (m_raycastHits.Count > 0)
                        {
                            if (ExtenderOptions.IsDebugging)
                            {
                                Essentials.Log.Info("Failed to spawn cargo ship: Ship path intersects another object");
                            }
                            return;
                        }
                    }
                }

                long spawnGroupId = MyPirateAntennas.GetPiratesId( );

                // The ships were collision-free. Now spawn them
                foreach (var shipPrefab in spawnGroup.Prefabs)
                {
                    // Yes, this could have been saved in the previous loop, but compared to (e.g.) raycasts, this does not take too much time to recalculate
                    Vector3D shipPosition    = Vector3D.Transform((Vector3D)shipPrefab.Position, originMatrix);
                    Vector3D shipDestination = shipPosition + directionMult;
                    Vector3D up = Vector3D.CalculatePerpendicularVector(-direction);

                    m_tmpGridList.Clear( );

                    // CH: We don't want a new identity for each ship anymore. We should handle that in a better way...

                    /*if (shipPrefab.ResetOwnership)
                     * {
                     * if (spawnGroupId == 0)
                     * {
                     * //This is not an NPC so that it doesn't show up in assign ownership drop down menu
                     * MyIdentity spawnGroupIdentity = Sync.Players.CreateNewIdentity("Neutral NPC");
                     * spawnGroupId = spawnGroupIdentity.IdentityId;
                     * }
                     * }*/

                    // Deploy ship
                    MyPrefabManager.Static.SpawnPrefab(
                        resultList: m_tmpGridList,
                        prefabName: shipPrefab.SubtypeId,
                        position: shipPosition,
                        forward: direction,
                        up: up,
                        initialLinearVelocity: shipPrefab.Speed * direction,
                        beaconName: shipPrefab.BeaconText,
                        spawningOptions: VRage.Game.ModAPI.SpawningOptions.RotateFirstCockpitTowardsDirection |
                        VRage.Game.ModAPI.SpawningOptions.SpawnRandomCargo |
                        VRage.Game.ModAPI.SpawningOptions.DisableDampeners,
                        ownerId: shipPrefab.ResetOwnership ? spawnGroupId : 0,
                        updateSync: true);

                    /*
                     * foreach (var grid in m_tmpGridList)
                     * {
                     * var cockpit = grid.GetFirstBlockOfType<MyCockpit>();
                     * if (cockpit != null)
                     * {
                     * MySimpleAutopilot ai = new MySimpleAutopilot(shipDestination, (Vector3)direction);
                     * cockpit.AttachAutopilot(ai);
                     * break;
                     * }
                     * }
                     */
                    m_tmpGridList.Clear( );
                }
            });
        }
Example #12
0
        public static void OnGlobalSpawnEvent(object senderEvent)
        {
            // Select a spawn group to spawn
            MySpawnGroupDefinition spawnGroup = PickRandomSpawnGroup();

            if (spawnGroup == null)
            {
                return;
            }

            spawnGroup.ReloadPrefabs();

            ProfilerShort.Begin("Generate position and direction");

            double   spawnDistance  = NEUTRAL_SHIP_SPAWN_DISTANCE;
            Vector3D playerPosition = Vector3D.Zero;
            bool     isWorldLimited = MyEntities.IsWorldLimited();
            int      numPlayers     = 0;

            if (isWorldLimited)
            {
                spawnDistance = Math.Min(spawnDistance, MyEntities.WorldSafeHalfExtent() - spawnGroup.SpawnRadius);
            }
            else
            {
                // In infinite worlds players can be thousands of kilometers away, so spawn ship around random player
                // so cargo ships will be spawned around every player at some time
                var players = MySession.Static.Players.GetOnlinePlayers();
                // In DS there can be no players connected
                numPlayers = Math.Max(0, players.Count - 1);
                int randomPlayerPosition = MyUtils.GetRandomInt(0, numPlayers);
                int i = 0;
                foreach (var player in players)
                {
                    if (i == randomPlayerPosition)
                    {
                        if (player.Character != null)
                        {
                            playerPosition = player.GetPosition();
                        }
                        break;
                    }
                    i++;
                }
            }
            if (spawnDistance < 0.0f)
            {
                MySandboxGame.Log.WriteLine("Not enough space in the world to spawn such a huge spawn group!");
                return;
            }

            double       forbiddenRadius = NEUTRAL_SHIP_FORBIDDEN_RADIUS;
            BoundingBoxD spawnBox;

            if (isWorldLimited)
            {
                spawnBox = new BoundingBoxD(new Vector3D(playerPosition - spawnDistance), new Vector3D(playerPosition + spawnDistance));
            }
            else
            {
                // We need to extend bouding box so cargo ships aren't spawned near other players
                GetSafeBoundingBoxForPlayers(playerPosition, spawnDistance, out spawnBox);
                // Forbidden radius is sphere around all players in box.
                // Bounding box is generated from players positions so their distance to center shall be same for all players
                forbiddenRadius += spawnBox.HalfExtents.Max() - NEUTRAL_SHIP_FORBIDDEN_RADIUS;
            }

            // Get the direction to the center and deviate it randomly
            Vector3D?origin = MyUtils.GetRandomBorderPosition(ref spawnBox);

            origin = MyEntities.TestPlaceInSpace(origin.Value, spawnGroup.SpawnRadius);
            if (!origin.HasValue)
            {
                if (++m_eventSpawnTry <= EVENT_SPAWN_TRY_MAX)
                {
                    MySandboxGame.Log.WriteLine("Could not spawn neutral ships - no free place found. Try " + m_eventSpawnTry + " of " + EVENT_SPAWN_TRY_MAX);

                    MyGlobalEvents.RescheduleEvent(senderEvent as MyGlobalEventBase, NEUTRAL_SHIP_RESCHEDULE_TIME);
                    ProfilerShort.End();
                    return;
                }
                else
                {
                    m_eventSpawnTry = 0;
                    return;
                }
            }
            m_eventSpawnTry = 0;

            // Radius in arc units of the forbidden sphere in the center, when viewed from origin
            float centerArcRadius = (float)Math.Atan(forbiddenRadius / (origin.Value - spawnBox.Center).Length());

            // Generate direction with elevation from centerArcRadius radians to (cAR + N_S_D_S) radians
            Vector3D direction = -Vector3D.Normalize(origin.Value);
            float    theta     = MyUtils.GetRandomFloat(centerArcRadius, centerArcRadius + NEUTRAL_SHIP_DIRECTION_SPREAD);
            float    phi       = MyUtils.GetRandomRadian();
            Vector3D cosVec    = Vector3D.CalculatePerpendicularVector(direction);
            Vector3D sinVec    = Vector3D.Cross(direction, cosVec);

            cosVec   *= (Math.Sin(theta) * Math.Cos(phi));
            sinVec   *= (Math.Sin(theta) * Math.Sin(phi));
            direction = direction * Math.Cos(theta) + cosVec + sinVec;

            Vector3D destination  = Vector3D.Zero;
            RayD     ray          = new RayD(origin.Value, direction);
            double?  intersection = ray.Intersects(spawnBox);
            Vector3D directionMult;

            if (!intersection.HasValue || intersection.Value < NEUTRAL_SHIP_MINIMAL_ROUTE_LENGTH)
            {
                directionMult = direction * NEUTRAL_SHIP_MINIMAL_ROUTE_LENGTH;
            }
            else
            {
                directionMult = direction * intersection.Value;
            }
            destination = origin.Value + directionMult;

            Vector3D upVector     = Vector3D.CalculatePerpendicularVector(direction);
            Vector3D rightVector  = Vector3D.Cross(direction, upVector);
            MatrixD  originMatrix = MatrixD.CreateWorld(origin.Value, direction, upVector);

            ProfilerShort.End();

            ProfilerShort.Begin("Check free space");

            // CH:TODO: Convex cast to detect collision
            // Check ships' path to avoid possible collisions. (TODO: But only if it is said in the definitions)
            m_raycastHits.Clear();
            foreach (var shipPrefab in spawnGroup.Prefabs)
            {
                var prefabDef = MyDefinitionManager.Static.GetPrefabDefinition(shipPrefab.SubtypeId);
                Debug.Assert(prefabDef != null);

                Vector3D shipPosition    = Vector3.Transform(shipPrefab.Position, originMatrix);
                Vector3D shipDestination = shipPosition + directionMult;
                float    radius          = prefabDef == null ? 10.0f : prefabDef.BoundingSphere.Radius;

                //these point checks could be done in the trajectory intersect, but checking points is faster than ray intersect
                if (MyGravityProviderSystem.IsPositionInNaturalGravity(shipPosition, spawnGroup.SpawnRadius))
                {
                    if (!MyFinalBuildConstants.IS_OFFICIAL)
                    {
                        MySandboxGame.Log.WriteLine("Could not spawn neutral ships: spawn point is inside gravity well");
                    }
                    MyGlobalEvents.RescheduleEvent(senderEvent as MyGlobalEventBase, NEUTRAL_SHIP_RESCHEDULE_TIME);
                    ProfilerShort.End();
                    return;
                }
                if (MyGravityProviderSystem.IsPositionInNaturalGravity(shipDestination, spawnGroup.SpawnRadius))
                {
                    if (!MyFinalBuildConstants.IS_OFFICIAL)
                    {
                        MySandboxGame.Log.WriteLine("Could not spawn neutral ships: destination point is inside gravity well");
                    }
                    MyGlobalEvents.RescheduleEvent(senderEvent as MyGlobalEventBase, NEUTRAL_SHIP_RESCHEDULE_TIME);
                    ProfilerShort.End();
                    return;
                }
                if (MyGravityProviderSystem.DoesTrajectoryIntersectNaturalGravity(shipPosition, shipDestination, spawnGroup.SpawnRadius + NEUTRAL_SHIP_SPAWN_OFFSET))
                {
                    if (!MyFinalBuildConstants.IS_OFFICIAL)
                    {
                        MySandboxGame.Log.WriteLine("Could not spawn neutral ships: flight path intersects gravity well");
                    }
                    MyGlobalEvents.RescheduleEvent(senderEvent as MyGlobalEventBase, NEUTRAL_SHIP_RESCHEDULE_TIME);
                    ProfilerShort.End();
                    return;
                }

                MyPhysics.CastRay(shipPosition, shipDestination, m_raycastHits, MyPhysics.CollisionLayers.ObjectDetectionCollisionLayer);
                if (m_raycastHits.Count > 0)
                {
                    if (!MyFinalBuildConstants.IS_OFFICIAL)
                    {
                        MySandboxGame.Log.WriteLine("Could not spawn neutral ships due to collision");
                    }
                    MyGlobalEvents.RescheduleEvent(senderEvent as MyGlobalEventBase, NEUTRAL_SHIP_RESCHEDULE_TIME);
                    ProfilerShort.End();
                    return;
                }

                for (int i = 0; i < 4; ++i)
                {
                    Vector3D shiftVector = upVector * m_upVecMultipliers[i] * radius + rightVector * m_rightVecMultipliers[i] * radius;
                    MyPhysics.CastRay(shipPosition + shiftVector, shipDestination + shiftVector, m_raycastHits, MyPhysics.CollisionLayers.ObjectDetectionCollisionLayer);

                    if (m_raycastHits.Count > 0)
                    {
                        if (!MyFinalBuildConstants.IS_OFFICIAL)
                        {
                            MySandboxGame.Log.WriteLine("Could not spawn neutral ships due to collision");
                        }
                        MyGlobalEvents.RescheduleEvent(senderEvent as MyGlobalEventBase, NEUTRAL_SHIP_RESCHEDULE_TIME);
                        ProfilerShort.End();
                        return;
                    }
                }
            }

            ProfilerShort.End();

            ProfilerShort.Begin("Spawn ships");

            long spawnGroupId = MyPirateAntennas.GetPiratesId();

            // The ships were collision-free. Now spawn them
            foreach (var shipPrefab in spawnGroup.Prefabs)
            {
                ProfilerShort.Begin(shipPrefab.BeaconText);

                // Yes, this could have been saved in the previous loop, but compared to (e.g.) raycasts, this does not take too much time to recalculate
                Vector3D shipPosition    = Vector3D.Transform((Vector3D)shipPrefab.Position, originMatrix);
                Vector3D shipDestination = shipPosition + directionMult;
                Vector3D up = Vector3D.CalculatePerpendicularVector(-direction);

                List <MyCubeGrid> tmpGridList = new List <MyCubeGrid>();

                // CH: We don't want a new identity for each ship anymore. We should handle that in a better way...

                /*if (shipPrefab.ResetOwnership)
                 * {
                 *  if (spawnGroupId == 0)
                 *  {
                 *      //This is not an NPC so that it doesn't show up in assign ownership drop down menu
                 *      MyIdentity spawnGroupIdentity = Sync.Players.CreateNewIdentity("Neutral NPC");
                 *      spawnGroupId = spawnGroupIdentity.IdentityId;
                 *  }
                 * }*/

                // Deploy ship
                ProfilerShort.Begin("Spawn cargo ship");
                Stack <Action> callbacks = new Stack <Action>();
                callbacks.Push(delegate()
                {
                    InitAutopilot(tmpGridList, shipDestination, direction);
                    foreach (var grid in tmpGridList)
                    {
                        Debug.Assert(grid.Physics.Enabled);
                        grid.ActivatePhysics(); //last chance to activate physics
                    }
                });
                MyPrefabManager.Static.SpawnPrefab(
                    resultList: tmpGridList,
                    prefabName: shipPrefab.SubtypeId,
                    position: shipPosition,
                    forward: direction,
                    up: up,
                    initialLinearVelocity: shipPrefab.Speed * direction,
                    beaconName: shipPrefab.BeaconText,
                    spawningOptions: VRage.Game.ModAPI.SpawningOptions.RotateFirstCockpitTowardsDirection |
                    VRage.Game.ModAPI.SpawningOptions.SpawnRandomCargo |
                    VRage.Game.ModAPI.SpawningOptions.DisableDampeners,
                    ownerId: shipPrefab.ResetOwnership ? spawnGroupId : 0,
                    callbacks: callbacks);
                ProfilerShort.End();
                ProfilerShort.End();
            }

            ProfilerShort.End();
        }
Example #13
0
        private bool SpawnDrone(MyRadioAntenna antenna, long ownerId, Vector3D position, MySpawnGroupDefinition spawnGroup, Vector3?spawnUp = null, Vector3?spawnForward = null)
        {
            long     antennaEntityId = antenna.EntityId;
            Vector3D antennaPos      = antenna.PositionComp.GetPosition();

            Vector3D upVector;

            var planet = MyGamePruningStructure.GetClosestPlanet(position);

            if (planet != null)
            {
                if (!MyGravityProviderSystem.IsPositionInNaturalGravity(antennaPos))
                {
                    MySandboxGame.Log.WriteLine("Couldn't spawn drone; antenna is not in natural gravity but spawn location is.");
                    return(false);
                }
                planet.CorrectSpawnLocation(ref position, spawnGroup.SpawnRadius * 2.0);
                upVector = position - planet.PositionComp.GetPosition();
                upVector.Normalize();
            }
            else
            {
                var totalGravityInPoint = MyGravityProviderSystem.CalculateTotalGravityInPoint(position);
                if (totalGravityInPoint != Vector3.Zero)
                {
                    upVector = -totalGravityInPoint;
                    upVector.Normalize();
                }
                else if (spawnUp != null)
                {
                    upVector = spawnUp.Value;
                }
                else
                {
                    upVector = MyUtils.GetRandomVector3Normalized();
                }
            }

            Vector3D direction = MyUtils.GetRandomPerpendicularVector(ref upVector);

            if (spawnForward != null)
            {
                // Align forward to up vector.
                Vector3 forward = spawnForward.Value;
                if (Math.Abs(Vector3.Dot(forward, upVector)) >= 0.98f)
                {
                    forward = Vector3.CalculatePerpendicularVector(upVector);
                }
                else
                {
                    Vector3 right = Vector3.Cross(forward, upVector);
                    right.Normalize();
                    forward = Vector3.Cross(upVector, right);
                    forward.Normalize();
                }

                direction = forward;
            }

            MatrixD originMatrix = MatrixD.CreateWorld(position, direction, upVector);

            foreach (var shipPrefab in spawnGroup.Prefabs)
            {
                Vector3D shipPosition = Vector3D.Transform((Vector3D)shipPrefab.Position, originMatrix);

                m_tmpGridList.Clear();

                MyPrefabManager.Static.SpawnPrefab(
                    resultList: m_tmpGridList,
                    prefabName: shipPrefab.SubtypeId,
                    position: shipPosition,
                    forward: direction,
                    up: upVector,
                    initialLinearVelocity: default(Vector3),
                    beaconName: null,
                    spawningOptions: VRage.Game.ModAPI.SpawningOptions.None,
                    ownerId: ownerId,
                    updateSync: true);

                foreach (var grid in m_tmpGridList)
                {
                    grid.ChangeGridOwnership(ownerId, MyOwnershipShareModeEnum.None);

                    MyRemoteControl firstRemote = null;

                    foreach (var block in grid.CubeBlocks)
                    {
                        if (block.FatBlock == null)
                        {
                            continue;
                        }

                        var pb = block.FatBlock as MyProgrammableBlock;
                        if (pb != null)
                        {
                            pb.SendRecompile();
                        }

                        var remote = block.FatBlock as MyRemoteControl;
                        if (firstRemote == null)
                        {
                            firstRemote = remote;
                        }
                    }

                    // If there's no remote control on the grid, we have to register it as is
                    RegisterDrone(antennaEntityId, (MyEntity)firstRemote ?? (MyEntity)grid);
                }

                m_tmpGridList.Clear();
            }
            return(true);
        }
        public void SaveToHangar()
        {
            if (!AlliancePlugin.config.HangarEnabled)
            {
                Context.Respond("Alliance hangar is not enabled.");
                return;
            }
            if (MySession.Static.IsSaveInProgress)
            {
                Context.Respond("World is saving! Try again soon.");
                return;
            }
            if (cooldowns.TryGetValue(Context.Player.IdentityId, out DateTime value))
            {
                if (DateTime.Now <= value)
                {
                    Context.Respond(GetCooldownMessage(value));
                    return;
                }
                else
                {
                    cooldowns[Context.Player.IdentityId] = DateTime.Now.AddSeconds(60);
                }
            }
            else
            {
                cooldowns.Add(Context.Player.IdentityId, DateTime.Now.AddSeconds(60));
            }
            if (MyGravityProviderSystem.IsPositionInNaturalGravity(Context.Player.GetPosition()))
            {
                Context.Respond("You cannot use this command in natural gravity!");
                return;
            }

            foreach (DeniedLocation denied in AlliancePlugin.HangarDeniedLocations)
            {
                if (Vector3.Distance(Context.Player.GetPosition(), new Vector3(denied.x, denied.y, denied.z)) <= denied.radius)
                {
                    Context.Respond("Cannot hangar here! Too close to a denied location.");
                    return;
                }
            }
            Boolean console = false;

            if (Context.Player == null)
            {
                console = true;
            }
            MyFaction fac = MySession.Static.Factions.GetPlayerFaction(Context.Player.IdentityId);

            if (fac == null)
            {
                Context.Respond("You must be in a faction to use alliance features.");
                return;
            }
            Alliance alliance = AlliancePlugin.GetAlliance(fac);

            if (alliance == null)
            {
                Context.Respond("You are not a member of an alliance.");
                return;
            }
            if (AlliancePlugin.HasFailedUpkeep(alliance))
            {
                Context.Respond("Alliance failed to pay upkeep. Upgrades disabled.");
                return;
            }
            if (!alliance.HasAccess(Context.Player.SteamUserId, AccessLevel.HangarSave))
            {
                Context.Respond("Current rank does not have access to hangar save.");
                return;
            }
            if (alliance.hasUnlockedHangar)
            {
                HangarData hangar = alliance.LoadHangar();
                if (hangar == null)
                {
                    Context.Respond("Error loading the hangar.");
                    return;
                }
                string name = "";
                int    pcu  = 0;
                if (hangar.getAvailableSlot() > 0)
                {
                    ConcurrentBag <MyGroups <MyCubeGrid, MyGridPhysicalGroupData> .Group> gridWithSubGrids = GridFinder.FindLookAtGridGroup(Context.Player.Character);
                    List <MyCubeGrid> grids = new List <MyCubeGrid>();
                    foreach (var item in gridWithSubGrids)
                    {
                        foreach (MyGroups <MyCubeGrid, MyGridPhysicalGroupData> .Node groupNodes in item.Nodes)
                        {
                            MyCubeGrid grid = groupNodes.NodeData;



                            if (grid.Projector != null)
                            {
                                continue;
                            }
                            if (FacUtils.IsOwnerOrFactionOwned(grid, Context.Player.IdentityId, true))
                            {
                                pcu += grid.BlocksPCU;
                                foreach (MyProjectorBase proj in grid.GetFatBlocks().OfType <MyProjectorBase>())
                                {
                                    proj.Clipboard.Clear();
                                }
                                grids.Add(grid);

                                if (name == "")
                                {
                                    name = grid.DisplayName;
                                    name = name.Replace("/", "");
                                    name = name.Replace("-", "");
                                    name = name.Replace("\\", "");
                                }
                            }
                            else
                            {
                                Context.Respond("The grid you are looking at includes a grid that isnt owned by you or a faction member.");
                                return;
                            }
                        }
                    }
                    if (grids.Count == 0)
                    {
                        Context.Respond("Could not find grid.");
                        return;
                    }
                    if (name == "")
                    {
                        name = "Temporary Name";
                    }
                    if (pcu >= AlliancePlugin.config.MaxHangarSlotPCU)
                    {
                        Context.Respond("PCU is greater than the configured maximum");
                        return;
                    }
                    bool result = hangar.SaveGridToHangar(name + "_" + string.Format("{0:yyyy-MM-dd_HH-mm-ss-fff}", DateTime.Now), Context.Player.SteamUserId, alliance, Context.Player.Character.PositionComp.GetPosition(), fac, grids, Context.Player.IdentityId);
                    if (!result)
                    {
                        Context.Respond("Could not save. Are enemies within 15km?");
                    }
                    else
                    {
                        Context.Respond("Grid saved.");

                        foreach (MyCubeGrid grid in grids)
                        {
                            if (grid != null)
                            {
                                grid.Close();
                            }
                        }
                    }
                }
                else
                {
                    Context.Respond("Hangar is full, to upgrade use !ah upgrade true.");
                }
            }
            else
            {
                Context.Respond("Alliance has not unlocked the hangar to unlock use !ah unlock.");
            }
        }