Пример #1
0
        public void AddPlayer(SkyPlayer player)
        {
            InstanceInfo bestGameInstance  = null;
            GameInfo     bestAvailableGame = null;

            //SkyUtil.log($"Checking available games from all instances for {GameName} ({_gameInstances.Count} total instances to search)");

            //Check current instance first
            if (_gameInstances.ContainsKey("local") && !SkyCoreAPI.IsRebootQueued)             //Avoid moving players to this server if it's about to reboot
            {
                InstanceInfo instanceInfo = _gameInstances["local"];

                string currentGameId = null;
                if (player.Level is GameLevel level)
                {
                    currentGameId = level.GameId;
                }

                GameInfo nextBestGame = null;
                foreach (GameInfo gameInfo in instanceInfo.AvailableGames)
                {
                    //SkyUtil.log($"Checking {gameInfo.GameId} on {instanceInfo.HostAddress}");
                    if ((bestAvailableGame == null || gameInfo.CurrentPlayers > bestAvailableGame.CurrentPlayers))
                    {
                        //Try to avoid placing the player in the game they just came from.
                        //Use this game as a fallback to avoid moving players off this instance.
                        if (currentGameId != null && currentGameId.Equals(gameInfo.GameId))
                        {
                            bestGameInstance = instanceInfo;
                            nextBestGame     = gameInfo;
                            continue;
                        }

                        //SkyUtil.log("Found best game!");
                        bestGameInstance  = instanceInfo;
                        bestAvailableGame = gameInfo;
                    }
                }

                if (bestAvailableGame == null)
                {
                    bestAvailableGame = nextBestGame;
                }
            }

            if (bestAvailableGame == null)
            {
                foreach (InstanceInfo instanceInfo in _gameInstances.Values)
                {
                    //SkyUtil.log($"Checking instance {instanceInfo.HostAddress} Available Servers: {instanceInfo.AvailableGames.Count}");
                    foreach (GameInfo gameInfo in instanceInfo.AvailableGames)
                    {
                        //SkyUtil.log($"Checking {gameInfo.GameId} on {instanceInfo.HostAddress}");
                        if (bestAvailableGame == null || gameInfo.CurrentPlayers > bestAvailableGame.CurrentPlayers)
                        {
                            //SkyUtil.log("Found best game!");
                            bestGameInstance  = instanceInfo;
                            bestAvailableGame = gameInfo;
                        }
                    }
                }
            }

            if (bestAvailableGame == null)
            {
                player.Freeze(false);                 //Unfreeze

                TitleUtil.SendCenteredSubtitle(player, $"§c§lGAME {(GetCurrentPlayers() > 0 ? "FULL" : "UNAVAILABLE")}§r\n§7Try joining again soon!", false);
            }
            else
            {
                if (player.Level is GameLevel level)
                {
                    if (player.Level.LevelId.Equals(bestAvailableGame.GameId))
                    {
                        return;                         //Cannot change game into current game.
                    }

                    //Remove player from level to avoid issues
                    level.RemovePlayer(player);
                }

                if (bestGameInstance.HostAddress.Equals("local"))
                {
                    SkyCoreAPI.Instance.GameModes[GameName].InstantQueuePlayer(player, bestAvailableGame);
                }
                else
                {
                    ExternalGameHandler.RedisPool.GetSubscriber().PublishAsync($"{GameName}_join", $"{player.Username}:{GameName}:{bestAvailableGame.GameId}");

                    McpeTransfer transferPacket = new McpeTransfer
                    {
                        serverAddress = bestGameInstance.HostAddress,
                        port          = bestGameInstance.HostPort
                    };

                    player.SendPackage(transferPacket);

                    MiNET.Worlds.Level playerLevel = player.Level;
                    RunnableTask.RunTaskLater(() =>
                    {
                        if (playerLevel.Players.ContainsKey(player.EntityId))
                        {
                            if (playerLevel is GameLevel gameLevel)
                            {
                                gameLevel.RemovePlayer(player);
                            }

                            playerLevel.RemoveEntity(player);

                            playerLevel.Players.TryRemove(player.EntityId, out _);
                        }
                    }, 1000);
                }
            }
        }
Пример #2
0
        //New GameLevel Method
        public void AddPlayer(SkyPlayer player)
        {
            if (player.Level != this && player.Level is GameLevel level)
            {
                level.RemovePlayer(player, true);         //Clear from old world
            }

            //Remove a player from _incomingPlayers only if it's non-empty.
            //Avoid claiming a lock for a useless check
            if (_incomingPlayers.Count > 0)
            {
                lock (_incomingPlayers)
                {
                    if (_incomingPlayers.ContainsKey(player.Username))
                    {
                        _incomingPlayers.Remove(player.Username);
                    }
                }
            }

            GameTeam defaultTeam = GetDefaultTeam();

            SetPlayerTeam(player, defaultTeam);
            //SkyUtil.log($"Added {player.Username} to team {defaultTeam.DisplayName} in game {GameId}");

            /*if (player.Level != this)
             * {
             *      //Only show the level transition screen to players changing games on this instance
             * //player.SpawnLevel(this, GameLevelInfo.LobbyLocation, !_incomingPlayers.ContainsKey(player.Username));
             * player.SpawnLevel(this, GameLevelInfo.LobbyLocation, false); //Remove loading screen to prevent 'building terrain' issue
             * }
             * else //Still teleport the player to the spawn location
             * {
             * player.Teleport(GameLevelInfo.LobbyLocation);
             * }*/

            //Fix for maps on first join to an instance
            player.SpawnLevel(this, GameLevelInfo.LobbyLocation, false);             //Remove loading screen to prevent 'building terrain' issue

            try
            {
                CurrentState.InitializePlayer(this, player);
            }
            catch (Exception e)
            {
                BugSnagUtil.ReportBug(e, this, CurrentState, player);
            }

            //Update Time
            McpeSetTime message = McpeSetTime.CreateObject();

            message.time = GameLevelInfo.WorldTime;
            player.SendPackage(message);

            //

            //Pending Tasks
            //Attempts to execute tasks like spawning NPCs in once a single player has loaded the world
            if (_shouldSchedule)
            {
                _shouldSchedule = false;

                if (_pendingTasks.Count > 0)
                {
                    foreach (SkyCoreAPI.PendingTask pendingTask in _pendingTasks)
                    {
                        RunnableTask.RunTaskLater(() =>
                        {
                            try
                            {
                                pendingTask.Invoke();
                            }
                            catch (Exception e)
                            {
                                BugSnagUtil.ReportBug(e, new AnonMetadatable((metadata) =>
                                {
                                    metadata.AddToTab("PendingTask", "Target", pendingTask.Target);
                                    metadata.AddToTab("PendingTask", "Method", pendingTask.Method);
                                }));
                            }
                        }, 250);                 //Small delay for the level to initialize
                    }

                    _pendingTasks.Clear();
                }
            }
        }