Exemple #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);
                }
            }
        }