示例#1
0
        public override void BeforeStart()
        {
            base.BeforeStart();

            // Make sure that the pirate identity exists
            if (m_piratesIdentityId != 0)
            {
                MyIdentity pirateIdentity = Sync.Players.TryGetIdentity(m_piratesIdentityId);
                Debug.Assert(pirateIdentity != null, "The pirate identity does not exist, although its ID was saved!");

                if (Sync.IsServer && pirateIdentity == null)
                {
                    Sync.Players.CreateNewIdentity(IDENTITY_NAME, m_piratesIdentityId, null);
                }
            }
            else
            {
                var identity = Sync.Players.CreateNewIdentity(IDENTITY_NAME);
                m_piratesIdentityId = identity.IdentityId;
            }

            if (!Sync.Players.IdentityIsNpc(m_piratesIdentityId))
            {
                Sync.Players.MarkIdentityAsNPC(m_piratesIdentityId);
            }

            // Make sure that all the drone entities exist
            foreach (var drone in m_droneInfos)
            {
                MyEntity entity;
                MyEntities.TryGetEntityById(drone.Key, out entity);
                if (entity == null)
                {
                    DroneInfo.Deallocate(drone.Value);
                    m_droneInfos.Remove(drone.Key);
                }
                else
                {
                    if (!MySession.Static.Settings.EnableDrones)
                    {
                        MyCubeGrid grid   = entity as MyCubeGrid;
                        var        remote = entity as MyRemoteControl;
                        if (grid == null)
                        {
                            grid = remote.CubeGrid;
                        }

                        UnregisterDrone(entity, immediate: false);
                        grid.SyncObject.SendCloseRequest();
                    }
                    else
                    {
                        RegisterDrone(drone.Value.AntennaEntityId, entity, immediate: false);
                    }
                }
            }
            m_droneInfos.ApplyRemovals();
        }
示例#2
0
        public void ChangeIdentity(MyIdentity newIdentity)
        {
            Debug.Assert(newIdentity != null, "Changing an identity of a controller to nobody, which does not make sense");
            Identity = newIdentity;

            if (IdentityChanged != null)
            {
                IdentityChanged(this, newIdentity);
            }
        }
        public MyPlayer CreateNewPlayer(MyIdentity identity, PlayerId id, string playerName)
        {
            Debug.Assert(Sync.IsServer);

            MyNetworkClient steamClient;
            Sync.Clients.TryGetClient(id.SteamId, out steamClient);
            Debug.Assert(steamClient != null, "Could not find a client for the new player!");
            if (steamClient == null) return null;

            var player = CreateNewPlayerInternal(identity, steamClient, playerName, ref id);
            if (player != null)
            {
                var msg = new PlayerCreatedMsg();
                msg.ClientSteamId = id.SteamId;
                msg.PlayerSerialId = id.SerialId;
                msg.IdentityId = identity.IdentityId;
                msg.DisplayName = playerName;

                Sync.Layer.SendMessageToAll(ref msg, MyTransportMessageEnum.Success);
            }
            return player;
        }
        public MyPlayer CreateNewPlayer(MyIdentity identity, MyNetworkClient steamClient, string playerName)
        {
            Debug.Assert(Sync.IsServer);

            // TODO: Limit number of players per client
            var playerId = FindFreePlayerId(steamClient.SteamUserId);
            return CreateNewPlayerInternal(identity, steamClient, playerName, ref playerId);
        }
        private void player_IdentityChanged(MyPlayer player, MyIdentity identity)
        {
            Debug.Assert(m_playerIdentityIds[player.Id] != identity.IdentityId, "Setting player identity to the same value. Is that what you want?");

            m_playerIdentityIds[player.Id] = identity.IdentityId;

            if (Sync.IsServer)
            {
                var msg = new PlayerIdentityChangedMsg();
                msg.ClientSteamId = player.Id.SteamId;
                msg.PlayerSerialId = player.Id.SerialId;
                msg.IdentityId = identity.IdentityId;

                Sync.Layer.SendMessageToAll(ref msg);
            }
        }
        private void AfterCreateIdentity(MyIdentity identity, bool addToNpcs = false)
        {
            if (addToNpcs)
            {
                MarkIdentityAsNPC(identity.IdentityId);
            }

            m_allIdentities.Add(identity.IdentityId, identity);

            if (Sync.IsServer)
            {
                IdentityCreatedMsg msg = new IdentityCreatedMsg();
                msg.IsNPC = addToNpcs;
                msg.IdentityId = identity.IdentityId;
                msg.DisplayName = identity.DisplayName;
                msg.Model = identity.Model;

                Sync.Layer.SendMessageToAll(ref msg);
            }
        }
        public override void BeforeStart()
        {
            base.BeforeStart();

            MyFaction pirateFaction = MySession.Static.Factions.TryGetFactionByTag(PIRATE_FACTION_TAG);

            Debug.Assert(pirateFaction != null, "No pirate faction in the world. Pirate antenan needs it.");

            if (pirateFaction != null)
            {
                // Make sure that the pirate identity exists
                if (m_piratesIdentityId != 0)
                {
                    if (Sync.IsServer)
                    {
                        MyIdentity pirateIdentity = Sync.Players.TryGetIdentity(m_piratesIdentityId);
                        Debug.Assert(pirateIdentity != null, "The pirate identity does not exist, although its ID was saved!");

                        if (pirateIdentity == null)
                        {
                            Sync.Players.CreateNewIdentity(IDENTITY_NAME, m_piratesIdentityId, null);
                        }

                        pirateIdentity.LastLoginTime = DateTime.Now;

                        // Check if he is already in a faction.
                        MyFaction oldPirateFaction = MySession.Static.Factions.GetPlayerFaction(m_piratesIdentityId);
                        if (oldPirateFaction == null)
                        {
                            MyFactionCollection.SendJoinRequest(pirateFaction.FactionId, m_piratesIdentityId);
                        }
                    }
                }
                else
                {
                    m_piratesIdentityId = pirateFaction.FounderId;
                }

                if (!Sync.Players.IdentityIsNpc(m_piratesIdentityId))
                {
                    Sync.Players.MarkIdentityAsNPC(m_piratesIdentityId);
                }
            }

            // Make sure that all the drone entities exist
            foreach (var drone in m_droneInfos)
            {
                MyEntity entity;
                MyEntities.TryGetEntityById(drone.Key, out entity);
                if (entity == null)
                {
                    DroneInfo.Deallocate(drone.Value);
                    m_droneInfos.Remove(drone.Key);
                }
                else
                {
                    if (!MySession.Static.Settings.EnableDrones)
                    {
                        MyCubeGrid grid   = entity as MyCubeGrid;
                        var        remote = entity as MyRemoteControl;
                        if (grid == null)
                        {
                            grid = remote.CubeGrid;
                        }

                        UnregisterDrone(entity, immediate: false);
                        grid.Close();
                        //grid.SyncObject.SendCloseRequest();
                    }
                    else
                    {
                        RegisterDrone(drone.Value.AntennaEntityId, entity, immediate: false);
                    }
                }
            }
            m_droneInfos.ApplyRemovals();
        }
示例#8
0
        public void ClearChatHistoryForPlayer(MyIdentity identity)
        {
            MySession.Static.ChatHistory.Remove(identity.IdentityId);

            foreach (var chatHistory in MySession.Static.ChatHistory.Values)
            {
                chatHistory.PlayerChatHistory.Remove(identity.IdentityId);
            }

            foreach (var factionChatHistory in MySession.Static.FactionChatHistory)
            {
                foreach (var chatItem in factionChatHistory.Chat)
                {
                    chatItem.PlayersToSendTo.Remove(identity.IdentityId);
                }
            }

            var handler = MySession.Static.ChatSystem.PlayerHistoryDeleted;
            if (handler != null)
            {
                handler();
            }
        }
        public MyPlayer CreateNewPlayer(MyIdentity identity, PlayerId id, string playerName)
        {
            Debug.Assert(Sync.IsServer);

            MyNetworkClient steamClient;
            Sync.Clients.TryGetClient(id.SteamId, out steamClient);
            Debug.Assert(steamClient != null, "Could not find a client for the new player!");
            if (steamClient == null) return null;

            var playerBuilder = new MyObjectBuilder_Player();
            playerBuilder.DisplayName = playerName;
            playerBuilder.IdentityId = identity.IdentityId;

            var player = CreateNewPlayerInternal(steamClient, id, playerBuilder);
            if (player != null)
            {
                List<Vector3> buildColors = null;
                if (!MyPlayer.IsColorsSetToDefaults(player.BuildColorSlots))
                    buildColors = player.BuildColorSlots;

                MyMultiplayer.RaiseStaticEvent(s => MyPlayerCollection.OnPlayerCreated, id.SteamId, id.SerialId, identity.IdentityId, playerName, buildColors);
            }
            return player;
        }
        public MyPlayer CreateNewPlayer(MyIdentity identity, MyNetworkClient steamClient, string playerName)
        {
            Debug.Assert(Sync.IsServer);

            // TODO: Limit number of players per client
            var playerId = FindFreePlayerId(steamClient.SteamUserId);

            var playerBuilder = new MyObjectBuilder_Player();
            playerBuilder.DisplayName = playerName;
            playerBuilder.IdentityId = identity.IdentityId;

            return CreateNewPlayerInternal(steamClient, playerId, playerBuilder);
        }
        private void player_IdentityChanged(MyPlayer player, MyIdentity identity)
        {
            Debug.Assert(m_playerIdentityIds[player.Id] != identity.IdentityId, "Setting player identity to the same value. Is that what you want?");

            m_playerIdentityIds[player.Id] = identity.IdentityId;

            if (Sync.IsServer)
            {
                MyMultiplayer.RaiseStaticEvent(s => MyPlayerCollection.OnPlayerIdentityChanged, player.Id.SteamId, player.Id.SerialId, identity.IdentityId);
            }
        }
        private void AfterCreateIdentity(MyIdentity identity, bool addToNpcs = false)
        {
            if (addToNpcs)
            {
                MarkIdentityAsNPC(identity.IdentityId);
            }

            // Had a crash here, added a check to prevent the crash, left an assert in case it happens regularly
            Debug.Assert(!m_allIdentities.ContainsKey(identity.IdentityId), "MyPlayerCollection m_allIdentities already contains a key for specified identity!");
            if (!m_allIdentities.ContainsKey(identity.IdentityId))
            {
                m_allIdentities.Add(identity.IdentityId, identity);

                identity.CharacterChanged += Identity_CharacterChanged;
                if (identity.Character != null)
                {
                    identity.Character.CharacterDied += Character_CharacterDied;
                }
            }

            if (Sync.IsServer)
            {
                MyMultiplayer.RaiseStaticEvent(s => MyPlayerCollection.OnIdentityCreated, addToNpcs, identity.IdentityId, identity.DisplayName);
            }

            var handler = IdentitiesChanged;
            if (handler != null) handler();
        }
        private void AfterCreateIdentity(MyIdentity identity, bool addToNpcs = false)
        {
            if (addToNpcs)
            {
                MarkIdentityAsNPC(identity.IdentityId);
            }

            m_allIdentities.Add(identity.IdentityId, identity);

            identity.CharacterChanged += Identity_CharacterChanged;
            if (identity.Character != null)
            {
                identity.Character.CharacterDied += Character_CharacterDied;
            }

            if (Sync.IsServer)
            {
                IdentityCreatedMsg msg = new IdentityCreatedMsg();
                msg.IsNPC = addToNpcs;
                msg.IdentityId = identity.IdentityId;
                msg.DisplayName = identity.DisplayName;
                msg.Model = identity.Model;

                Sync.Layer.SendMessageToAll(ref msg);
            }

            var handler = IdentitiesChanged;
            if (handler != null) handler();
        }
        public MyPlayer CreateNewPlayer(MyIdentity identity, PlayerId id, string playerName)
        {
            Debug.Assert(Sync.IsServer);

            MyNetworkClient steamClient;
            Sync.Clients.TryGetClient(id.SteamId, out steamClient);
            Debug.Assert(steamClient != null, "Could not find a client for the new player!");
            if (steamClient == null) return null;

            var playerBuilder = new MyObjectBuilder_Player();
            playerBuilder.DisplayName = playerName;
            playerBuilder.IdentityId = identity.IdentityId;

            var player = CreateNewPlayerInternal(steamClient, id, playerBuilder);
            if (player != null)
            {
                var msg = new PlayerCreatedMsg();
                msg.ClientSteamId = id.SteamId;
                msg.PlayerSerialId = id.SerialId;
                msg.IdentityId = identity.IdentityId;
                msg.DisplayName = playerName;
                msg.BuildColors = null;
                if (!MyPlayer.IsColorsSetToDefaults(player.BuildColorSlots))
                    msg.BuildColors = player.BuildColorSlots;

                Sync.Layer.SendMessageToAll(ref msg, MyTransportMessageEnum.Success);
            }
            return player;
        }
        //public MyPlayer InitNewPlayer(MyIdentity identity, PlayerId id, string playerName)
        //{
        //    MyNetworkClient steamClient;
        //    Sync.Clients.TryGetClient(id.SteamId, out steamClient);
        //    Debug.Assert(steamClient != null, "Could not find a client for the new player!");
        //    if (steamClient == null) return null;

        //    return CreateNewPlayerInternal(identity, steamClient, playerName, ref id);
        //}

        public MyPlayer InitNewPlayer(MyIdentity identity, PlayerId id, MyObjectBuilder_Player playerOb)
        {
            MyNetworkClient steamClient;
            Sync.Clients.TryGetClient(id.SteamId, out steamClient);
            Debug.Assert(steamClient != null, "Could not find a client for the new player!");
            if (steamClient == null) return null;

            MyPlayer playerInstance = CreateNewPlayerInternal(identity, steamClient, playerOb.DisplayName, ref id);
            return playerInstance;
        }
示例#16
0
        public static bool RetryFactionMessage(long factionId1, long factionId2, MyFactionChatItem chatItem, MyIdentity currentSenderIdentity)
        {
            Debug.Assert(Sync.IsServer, "Faction message retries should only be done on server");

            if (currentSenderIdentity.Character == null)
            {
                return false;
            }

            m_tempValidIds.Clear();
            foreach (var playerToSendTo in chatItem.PlayersToSendTo)
            {
                if (!playerToSendTo.Value)
                {
                    long receiverIdentityId = playerToSendTo.Key;
                    var receiverId = MySession.Static.Players.TryGetIdentity(receiverIdentityId);
                    if (receiverId != null && receiverId.Character != null && MyAntennaSystem.CheckConnection(currentSenderIdentity, receiverId))
                    {
                        m_tempValidIds.Add(receiverIdentityId);
                    }
                }
            }

            if (m_tempValidIds.Count == 0)
            {
                return false;
            }

            foreach (var id in m_tempValidIds)
            {
                chatItem.PlayersToSendTo[id] = true;
            }

            var msg = new SendNewFactionMessageMsg();

            msg.FactionId1 = factionId1;
            msg.FactionId2 = factionId2;
            msg.CharacterEntityId = currentSenderIdentity.Character.EntityId;
            msg.ChatItem = chatItem.GetObjectBuilder();

            var confirmMessage = new ConfirmFactionMessageMsg();
            confirmMessage.CharacterEntityId = currentSenderIdentity.Character.EntityId;

            confirmMessage.FactionId1 = msg.FactionId1;
            confirmMessage.FactionId2 = msg.FactionId2;
            confirmMessage.OriginalSenderId = chatItem.IdentityId;
            confirmMessage.Timestamp = chatItem.Timestamp.Ticks;
            confirmMessage.Text = msg.ChatItem.Text;

            foreach (var id in m_tempValidIds)
            {
                MyPlayer.PlayerId receiverPlayerId;
                MySession.Static.Players.TryGetPlayerId(id, out receiverPlayerId);
                ulong steamId = receiverPlayerId.SteamId;

                Sync.Layer.SendMessage(ref msg, steamId, MyTransportMessageEnum.Success);
            }
            foreach (var id in m_tempValidIds)
            {
                confirmMessage.ReceiverId = id;

                //Send confimation to members of both factions
                SendConfirmMessageToFaction(confirmMessage.FactionId1, chatItem.PlayersToSendTo, ref confirmMessage);
                if (confirmMessage.FactionId1 != confirmMessage.FactionId2)
                {
                    SendConfirmMessageToFaction(confirmMessage.FactionId2, chatItem.PlayersToSendTo, ref confirmMessage);
                }
            }

            return true;
        }
        private void RefreshPlayerChatHistory(MyIdentity playerIdentity)
        {
            m_chatHistory.Clear();
            var history = MyChatSystem.GetChatHistory(MySession.Static.LocalPlayerId);
            
            var playerId = playerIdentity.IdentityId;
            MyPlayerChatHistory playerChat;
            if (history.PlayerChatHistory.TryGetValue(playerId, out playerChat))
            {
                var chat = playerChat.Chat;
                foreach (var text in chat)
                {
                    var identity = MySession.Static.Players.TryGetIdentity(text.IdentityId);

                    if (identity == null) continue;
                    bool isPlayer = identity.IdentityId == MySession.Static.LocalPlayerId;

                    m_chatHistory.AppendText(identity.DisplayName, isPlayer ? MyFontEnum.DarkBlue : MyFontEnum.Blue, m_chatHistory.TextScale, Vector4.One);
                    if (!text.Sent)
                    {
                        m_tempStringBuilder.Clear();
                        m_tempStringBuilder.Append(" (");
                        m_tempStringBuilder.Append(MyTexts.GetString(MySpaceTexts.TerminalTab_Chat_Pending));
                        m_tempStringBuilder.Append(")");
                        m_chatHistory.AppendText(m_tempStringBuilder, MyFontEnum.Red, m_chatHistory.TextScale, Vector4.One);
                    }
                    m_chatHistory.AppendText(": ", isPlayer ? MyFontEnum.DarkBlue : MyFontEnum.Blue, m_chatHistory.TextScale, Vector4.One);
                    m_chatHistory.AppendText(text.Text, MyFontEnum.White, m_chatHistory.TextScale, Vector4.One);
                    m_chatHistory.AppendLine();
                }
            }

            m_factionList.SelectedItems.Clear();
            m_chatHistory.ScrollbarOffset = 1.0f;
        }
 private void ShowPlayerNotOnlineMessage(MyIdentity identity)
 {
     var messageBox = MyGuiSandbox.CreateMessageBox(
             buttonType: MyMessageBoxButtonsType.OK,
                 messageText: new StringBuilder().AppendFormat(MyCommonTexts.MessageBoxTextPlayerNotOnline, identity.DisplayName),
                 messageCaption: MyTexts.Get(MyCommonTexts.MessageBoxCaptionError),
                 canHideOthers: false,
                 callback: (result) =>
                 {
                     RecreateControls();
                 }
             );
     MyGuiSandbox.AddScreen(messageBox);
 }
        public static bool RetryFactionMessage(long factionId1, long factionId2, MyFactionChatItem chatItem, MyIdentity currentSenderIdentity)
        {
            Debug.Assert(Sync.IsServer, "Faction message retries should only be done on server");

            if (currentSenderIdentity == null || currentSenderIdentity.Character == null)
            {
                return false;
            }

            m_tempValidIds.Clear();
            foreach (var playerToSendTo in chatItem.PlayersToSendTo)
            {
                if (!playerToSendTo.Value)
                {
                    long receiverIdentityId = playerToSendTo.Key;
                    if (Sync.Players.IdentityIsNpc(receiverIdentityId))
                    {
                        continue;
                    }
                    MyIdentity receiverId = MySession.Static.Players.TryGetIdentity(receiverIdentityId);
                    if (receiverId != null && receiverId.Character != null && MyAntennaSystem.Static.CheckConnection(currentSenderIdentity, receiverId))
                    {
                        m_tempValidIds.Add(receiverIdentityId);
                    }
                }
            }

            if (m_tempValidIds.Count == 0)
            {
                return false;
            }

            foreach (var id in m_tempValidIds)
            {
                chatItem.PlayersToSendTo[id] = true;
            }

            foreach (var id in m_tempValidIds)
            {
                MyPlayer.PlayerId receiverPlayerId;
                MySession.Static.Players.TryGetPlayerId(id, out receiverPlayerId);
                ulong steamId = receiverPlayerId.SteamId;

                MyMultiplayer.RaiseStaticEvent(x => OnFactionMessageSuccess, factionId1, factionId2, chatItem.GetObjectBuilder(), new EndpointId(steamId));
            }
            foreach (var id in m_tempValidIds)
            {
                //Send confirmation to members of both factions
                SendConfirmMessageToFaction(factionId1, chatItem.PlayersToSendTo, factionId1, factionId2, chatItem.IdentityId, chatItem.Timestamp.Ticks, id, chatItem.Text);
                if (factionId1 != factionId2)
                {
                    SendConfirmMessageToFaction(factionId2, chatItem.PlayersToSendTo, factionId1, factionId2, chatItem.IdentityId, chatItem.Timestamp.Ticks, id, chatItem.Text);
                }
            }

            return true;
        }
        private MyPlayer CreateNewPlayerInternal(MyIdentity identity, MyNetworkClient steamClient, string playerName, ref PlayerId playerId)
        {
            MyPlayer newPlayer = new MyPlayer(steamClient, playerName, playerId);

            if (!m_playerIdentityIds.ContainsKey(playerId))
            {
                m_playerIdentityIds.Add(playerId, identity.IdentityId);
            }

            newPlayer.ChangeIdentity(identity);
            newPlayer.IdentityChanged += player_IdentityChanged;
            newPlayer.Controller.ControlledEntityChanged += controller_ControlledEntityChanged;

            AddPlayer(playerId, newPlayer);

            return newPlayer;
        }
        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.FindFreePlace(origin.Value, spawnGroup.SpawnRadius);
            if (!origin.HasValue)
            {
                MySandboxGame.Log.WriteLine("Could not spawn neutral ships - no free place found");
                MyGlobalEvents.RescheduleEvent(senderEvent as MyGlobalEventBase, NEUTRAL_SHIP_RESCHEDULE_TIME);
                ProfilerShort.End();
                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);

            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;

                MyPhysics.CastRay(shipPosition, shipDestination, m_raycastHits, MyPhysics.ObjectDetectionCollisionLayer);
                if (m_raycastHits.Count() > 0)
                {
                    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.ObjectDetectionCollisionLayer);

                    if (m_raycastHits.Count() > 0)
                    {
                        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");

            //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");
            long       spawnGroupId       = spawnGroupIdentity.IdentityId;

            // 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);

                m_tmpGridList.Clear();

                // Deploy ship
                ProfilerShort.Begin("Spawn cargo ship");
                MyPrefabManager.Static.SpawnPrefab(
                    resultList: m_tmpGridList,
                    prefabName: shipPrefab.SubtypeId,
                    position: shipPosition,
                    forward: direction,
                    up: up,
                    initialLinearVelocity: shipPrefab.Speed * direction,
                    beaconName: shipPrefab.BeaconText,
                    spawningOptions: Sandbox.ModAPI.SpawningOptions.RotateFirstCockpitTowardsDirection |
                    Sandbox.ModAPI.SpawningOptions.SpawnRandomCargo |
                    Sandbox.ModAPI.SpawningOptions.DisableDampeners,
                    updateSync: true);
                ProfilerShort.End();

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

                    var cockpit = grid.GetFirstBlockOfType <MyCockpit>();
                    if (cockpit != null)
                    {
                        MySimpleAutopilot ai = new MySimpleAutopilot(shipDestination, (Vector3)direction);
                        cockpit.AttachAutopilot(ai);
                        break;
                    }
                }

                m_tmpGridList.Clear();

                ProfilerShort.End();
            }

            ProfilerShort.End();
        }
        private MyPlayer CreateNewPlayerInternal(MyIdentity identity, MyNetworkClient steamClient, string playerName, ref PlayerId playerId)
        {
            MyPlayer newPlayer = new MyPlayer(steamClient, playerName, playerId);

            if (!m_playerIdentityIds.ContainsKey(playerId))
            {
                m_playerIdentityIds.Add(playerId, identity.IdentityId);
            }

            newPlayer.ChangeIdentity(identity);
            newPlayer.IdentityChanged += player_IdentityChanged;
            newPlayer.Controller.ControlledEntityChanged += controller_ControlledEntityChanged;

            AddPlayer(playerId, newPlayer);

            if (MyFakes.ENABLE_MISSION_TRIGGERS && MySessionComponentMissionTriggers.Static!=null)
                MySessionComponentMissionTriggers.Static.TryCreateFromDefault(playerId);

            return newPlayer;
        }