Example #1
0
        public AnonymousProfileTooltipLogic(Widget widget, OrderManager orderManager, Session.Client client)
        {
            var address             = LobbyUtils.GetExternalIP(client, orderManager);
            var cachedDescriptiveIP = address ?? "Unknown IP";

            var nameLabel = widget.Get <LabelWidget>("NAME");
            var nameFont  = Game.Renderer.Fonts[nameLabel.Font];

            widget.Bounds.Width = nameFont.Measure(nameLabel.Text).X + 2 * nameLabel.Bounds.Left;

            var ipLabel = widget.Get <LabelWidget>("IP");

            ipLabel.GetText = () => cachedDescriptiveIP;

            var locationLabel       = widget.Get <LabelWidget>("LOCATION");
            var cachedCountryLookup = GeoIP.LookupCountry(address);

            locationLabel.GetText = () => cachedCountryLookup;

            if (client.IsAdmin)
            {
                var adminLabel = widget.Get("GAME_ADMIN");
                adminLabel.IsVisible  = () => client.IsAdmin;
                widget.Bounds.Height += adminLabel.Bounds.Height;
            }
        }
Example #2
0
        void ValidateClient(Connection newConn, string data)
        {
            try
            {
                if (State == ServerState.GameStarted)
                {
                    Log.Write("server", "Rejected connection from {0}; game is already started.",
                              newConn.Socket.RemoteEndPoint);

                    SendOrderTo(newConn, "ServerError", "The game has already started");
                    DropClient(newConn);
                    return;
                }

                var handshake = HandshakeResponse.Deserialize(data);

                if (!string.IsNullOrEmpty(Settings.Password) && handshake.Password != Settings.Password)
                {
                    var message = string.IsNullOrEmpty(handshake.Password) ? "Server requires a password" : "Incorrect password";
                    SendOrderTo(newConn, "AuthenticationError", message);
                    DropClient(newConn);
                    return;
                }

                var ipAddress = ((IPEndPoint)newConn.Socket.RemoteEndPoint).Address;
                var client    = new Session.Client
                {
                    Name                = OpenRA.Settings.SanitizedPlayerName(handshake.Client.Name),
                    IPAddress           = ipAddress.ToString(),
                    AnonymizedIPAddress = Type != ServerType.Local && Settings.ShareAnonymizedIPs ? Session.AnonymizeIP(ipAddress) : null,
                    Location            = GeoIP.LookupCountry(ipAddress),
                    Index               = newConn.PlayerIndex,
                    PreferredColor      = handshake.Client.PreferredColor,
                    Color               = handshake.Client.Color,
                    Faction             = "Random",
                    SpawnPoint          = 0,
                    Team                = 0,
                    State               = Session.ClientState.Invalid,
                };

                if (ModData.Manifest.Id != handshake.Mod)
                {
                    Log.Write("server", "Rejected connection from {0}; mods do not match.",
                              newConn.Socket.RemoteEndPoint);

                    SendOrderTo(newConn, "ServerError", "Server is running an incompatible mod");
                    DropClient(newConn);
                    return;
                }

                if (ModData.Manifest.Metadata.Version != handshake.Version)
                {
                    Log.Write("server", "Rejected connection from {0}; Not running the same version.",
                              newConn.Socket.RemoteEndPoint);

                    SendOrderTo(newConn, "ServerError", "Server is running an incompatible version");
                    DropClient(newConn);
                    return;
                }

                if (handshake.OrdersProtocol != ProtocolVersion.Orders)
                {
                    Log.Write("server", "Rejected connection from {0}; incompatible Orders protocol version {1}.",
                              newConn.Socket.RemoteEndPoint, handshake.OrdersProtocol);

                    SendOrderTo(newConn, "ServerError", "Server is running an incompatible protocol");
                    DropClient(newConn);
                    return;
                }

                // Check if IP is banned
                var bans = Settings.Ban.Union(TempBans);
                if (bans.Contains(client.IPAddress))
                {
                    Log.Write("server", "Rejected connection from {0}; Banned.", newConn.Socket.RemoteEndPoint);
                    SendOrderTo(newConn, "ServerError", "You have been {0} from the server".F(Settings.Ban.Contains(client.IPAddress) ? "banned" : "temporarily banned"));
                    DropClient(newConn);
                    return;
                }

                Action completeConnection = () =>
                {
                    lock (LobbyInfo)
                    {
                        client.Slot    = LobbyInfo.FirstEmptySlot();
                        client.IsAdmin = !LobbyInfo.Clients.Any(c1 => c1.IsAdmin);

                        if (client.IsObserver && !LobbyInfo.GlobalSettings.AllowSpectators)
                        {
                            SendOrderTo(newConn, "ServerError", "The game is full");
                            DropClient(newConn);
                            return;
                        }

                        if (client.Slot != null)
                        {
                            SyncClientToPlayerReference(client, Map.Players.Players[client.Slot]);
                        }
                        else
                        {
                            client.Color = Color.White;
                        }

                        // Promote connection to a valid client
                        PreConns.Remove(newConn);
                        Conns.Add(newConn);
                        LobbyInfo.Clients.Add(client);
                        newConn.Validated = true;

                        var clientPing = new Session.ClientPing {
                            Index = client.Index
                        };
                        LobbyInfo.ClientPings.Add(clientPing);

                        Log.Write("server", "Client {0}: Accepted connection from {1}.",
                                  newConn.PlayerIndex, newConn.Socket.RemoteEndPoint);

                        if (client.Fingerprint != null)
                        {
                            Log.Write("server", "Client {0}: Player fingerprint is {1}.",
                                      newConn.PlayerIndex, client.Fingerprint);
                        }

                        foreach (var t in serverTraits.WithInterface <IClientJoined>())
                        {
                            t.ClientJoined(this, newConn);
                        }

                        SyncLobbyInfo();

                        Log.Write("server", "{0} ({1}) has joined the game.",
                                  client.Name, newConn.Socket.RemoteEndPoint);

                        // Report to all other players
                        SendMessage("{0} has joined the game.".F(client.Name), newConn);

                        // Send initial ping
                        SendOrderTo(newConn, "Ping", Game.RunTime.ToString(CultureInfo.InvariantCulture));

                        if (Type == ServerType.Dedicated)
                        {
                            var motdFile = Platform.ResolvePath(Platform.SupportDirPrefix, "motd.txt");
                            if (!File.Exists(motdFile))
                            {
                                File.WriteAllText(motdFile, "Welcome, have fun and good luck!");
                            }

                            var motd = File.ReadAllText(motdFile);
                            if (!string.IsNullOrEmpty(motd))
                            {
                                SendOrderTo(newConn, "Message", motd);
                            }
                        }

                        if (Map.DefinesUnsafeCustomRules)
                        {
                            SendOrderTo(newConn, "Message", "This map contains custom rules. Game experience may change.");
                        }

                        if (!LobbyInfo.GlobalSettings.EnableSingleplayer)
                        {
                            SendOrderTo(newConn, "Message", TwoHumansRequiredText);
                        }
                        else if (Map.Players.Players.Where(p => p.Value.Playable).All(p => !p.Value.AllowBots))
                        {
                            SendOrderTo(newConn, "Message", "Bots have been disabled on this map.");
                        }
                    }
                };

                if (Type == ServerType.Local)
                {
                    // Local servers can only be joined by the local client, so we can trust their identity without validation
                    client.Fingerprint = handshake.Fingerprint;
                    completeConnection();
                }
                else if (!string.IsNullOrEmpty(handshake.Fingerprint) && !string.IsNullOrEmpty(handshake.AuthSignature))
                {
                    waitingForAuthenticationCallback++;

                    Action <DownloadDataCompletedEventArgs> onQueryComplete = i =>
                    {
                        PlayerProfile profile = null;

                        if (i.Error == null)
                        {
                            try
                            {
                                var yaml = MiniYaml.FromString(Encoding.UTF8.GetString(i.Result)).First();
                                if (yaml.Key == "Player")
                                {
                                    profile = FieldLoader.Load <PlayerProfile>(yaml.Value);

                                    var publicKey  = Encoding.ASCII.GetString(Convert.FromBase64String(profile.PublicKey));
                                    var parameters = CryptoUtil.DecodePEMPublicKey(publicKey);
                                    if (!profile.KeyRevoked && CryptoUtil.VerifySignature(parameters, newConn.AuthToken, handshake.AuthSignature))
                                    {
                                        client.Fingerprint = handshake.Fingerprint;
                                        Log.Write("server", "{0} authenticated as {1} (UID {2})", newConn.Socket.RemoteEndPoint,
                                                  profile.ProfileName, profile.ProfileID);
                                    }
                                    else if (profile.KeyRevoked)
                                    {
                                        profile = null;
                                        Log.Write("server", "{0} failed to authenticate as {1} (key revoked)", newConn.Socket.RemoteEndPoint, handshake.Fingerprint);
                                    }
                                    else
                                    {
                                        profile = null;
                                        Log.Write("server", "{0} failed to authenticate as {1} (signature verification failed)",
                                                  newConn.Socket.RemoteEndPoint, handshake.Fingerprint);
                                    }
                                }
                                else
                                {
                                    Log.Write("server", "{0} failed to authenticate as {1} (invalid server response: `{2}` is not `Player`)",
                                              newConn.Socket.RemoteEndPoint, handshake.Fingerprint, yaml.Key);
                                }
                            }
                            catch (Exception ex)
                            {
                                Log.Write("server", "{0} failed to authenticate as {1} (exception occurred)",
                                          newConn.Socket.RemoteEndPoint, handshake.Fingerprint);
                                Log.Write("server", ex.ToString());
                            }
                        }
                        else
                        {
                            Log.Write("server", "{0} failed to authenticate as {1} (server error: `{2}`)",
                                      newConn.Socket.RemoteEndPoint, handshake.Fingerprint, i.Error);
                        }

                        delayedActions.Add(() =>
                        {
                            var notAuthenticated = Type == ServerType.Dedicated && profile == null && (Settings.RequireAuthentication || Settings.ProfileIDWhitelist.Any());
                            var blacklisted      = Type == ServerType.Dedicated && profile != null && Settings.ProfileIDBlacklist.Contains(profile.ProfileID);
                            var notWhitelisted   = Type == ServerType.Dedicated && Settings.ProfileIDWhitelist.Any() &&
                                                   (profile == null || !Settings.ProfileIDWhitelist.Contains(profile.ProfileID));

                            if (notAuthenticated)
                            {
                                Log.Write("server", "Rejected connection from {0}; Not authenticated.", newConn.Socket.RemoteEndPoint);
                                SendOrderTo(newConn, "ServerError", "Server requires players to have an OpenRA forum account");
                                DropClient(newConn);
                            }
                            else if (blacklisted || notWhitelisted)
                            {
                                if (blacklisted)
                                {
                                    Log.Write("server", "Rejected connection from {0}; In server blacklist.", newConn.Socket.RemoteEndPoint);
                                }
                                else
                                {
                                    Log.Write("server", "Rejected connection from {0}; Not in server whitelist.", newConn.Socket.RemoteEndPoint);
                                }

                                SendOrderTo(newConn, "ServerError", "You do not have permission to join this server");
                                DropClient(newConn);
                            }
                            else
                            {
                                completeConnection();
                            }

                            waitingForAuthenticationCallback--;
                        }, 0);
                    };

                    new Download(playerDatabase.Profile + handshake.Fingerprint, _ => { }, onQueryComplete);
                }
                else
                {
                    if (Type == ServerType.Dedicated && (Settings.RequireAuthentication || Settings.ProfileIDWhitelist.Any()))
                    {
                        Log.Write("server", "Rejected connection from {0}; Not authenticated.", newConn.Socket.RemoteEndPoint);
                        SendOrderTo(newConn, "ServerError", "Server requires players to have an OpenRA forum account");
                        DropClient(newConn);
                    }
                    else
                    {
                        completeConnection();
                    }
                }
            }
            catch (Exception ex)
            {
                Log.Write("server", "Dropping connection {0} because an error occurred:", newConn.Socket.RemoteEndPoint);
                Log.Write("server", ex.ToString());
                DropClient(newConn);
            }
        }
Example #3
0
        List <Widget> LoadGameRows(List <GameServer> games, out ScrollItemWidget nextServerRow)
        {
            nextServerRow = null;
            var rows = new List <Widget>();
            var mods = games.GroupBy(g => g.ModLabel)
                       .OrderByDescending(g => GroupSortOrder(g.First()))
                       .ThenByDescending(g => g.Count());

            foreach (var modGames in mods)
            {
                if (modGames.All(Filtered))
                {
                    continue;
                }

                var header = ScrollItemWidget.Setup(headerTemplate, () => true, () => { });

                var headerTitle = modGames.First().ModLabel;
                header.Get <LabelWidget>("LABEL").GetText = () => headerTitle;
                rows.Add(header);

                Func <GameServer, int> listOrder = g =>
                {
                    // Servers waiting for players are always first
                    if (g.State == (int)ServerState.WaitingPlayers && g.Players > 0)
                    {
                        return(0);
                    }

                    // Then servers with spectators
                    if (g.State == (int)ServerState.WaitingPlayers && g.Spectators > 0)
                    {
                        return(1);
                    }

                    // Then active games
                    if (g.State >= (int)ServerState.GameStarted)
                    {
                        return(2);
                    }

                    // Empty servers are shown at the end because a flood of empty servers
                    // at the top of the game list make the community look dead
                    return(3);
                };

                foreach (var modGamesByState in modGames.GroupBy(listOrder).OrderBy(g => g.Key))
                {
                    // Sort 'Playing' games by Started, others by number of players
                    foreach (var game in modGamesByState.Key == 2 ? modGamesByState.OrderByDescending(g => g.Started) : modGamesByState.OrderByDescending(g => g.Players))
                    {
                        if (Filtered(game))
                        {
                            continue;
                        }

                        var canJoin = game.IsJoinable;
                        var item    = ScrollItemWidget.Setup(serverTemplate, () => currentServer == game, () => SelectServer(game), () => onJoin(game));
                        var title   = item.GetOrNull <LabelWidget>("TITLE");
                        if (title != null)
                        {
                            var font  = Game.Renderer.Fonts[title.Font];
                            var label = WidgetUtils.TruncateText(game.Name, title.Bounds.Width, font);
                            title.GetText  = () => label;
                            title.GetColor = () => canJoin ? title.TextColor : incompatibleGameColor;
                        }

                        var password = item.GetOrNull <ImageWidget>("PASSWORD_PROTECTED");
                        if (password != null)
                        {
                            password.IsVisible    = () => game.Protected;
                            password.GetImageName = () => canJoin ? "protected" : "protected-disabled";
                        }

                        var players = item.GetOrNull <LabelWithTooltipWidget>("PLAYERS");
                        if (players != null)
                        {
                            var label = "{0} / {1}".F(game.Players + game.Bots, game.MaxPlayers + game.Bots)
                                        + (game.Spectators > 0 ? " + {0}".F(game.Spectators) : "");

                            var color = canJoin ? players.TextColor : incompatibleGameColor;
                            players.GetText  = () => label;
                            players.GetColor = () => color;

                            if (game.Clients.Any())
                            {
                                var displayClients = game.Clients.Select(c => c.Name);
                                if (game.Clients.Length > 10)
                                {
                                    displayClients = displayClients
                                                     .Take(9)
                                                     .Append("+ {0} other players".F(game.Clients.Length - 9));
                                }

                                var tooltip = displayClients.JoinWith("\n");
                                players.GetTooltipText = () => tooltip;
                            }
                            else
                            {
                                players.GetTooltipText = null;
                            }
                        }

                        var state = item.GetOrNull <LabelWidget>("STATUS");
                        if (state != null)
                        {
                            var label = game.State >= (int)ServerState.GameStarted ?
                                        "Playing" : "Waiting";
                            state.GetText = () => label;

                            var color = GetStateColor(game, state, !canJoin);
                            state.GetColor = () => color;
                        }

                        var location = item.GetOrNull <LabelWidget>("LOCATION");
                        if (location != null)
                        {
                            var font = Game.Renderer.Fonts[location.Font];
                            var cachedServerLocation = game.Id != -1 ? GeoIP.LookupCountry(game.Address.Split(':')[0]) : "Local Network";
                            var label = WidgetUtils.TruncateText(cachedServerLocation, location.Bounds.Width, font);
                            location.GetText  = () => label;
                            location.GetColor = () => canJoin ? location.TextColor : incompatibleGameColor;
                        }

                        if (currentServer != null && game.Address == currentServer.Address)
                        {
                            nextServerRow = item;
                        }

                        rows.Add(item);
                    }
                }
            }

            return(rows);
        }
Example #4
0
        public ClientTooltipLogic(Widget widget, TooltipContainerWidget tooltipContainer, OrderManager orderManager, int clientIndex)
        {
            var admin     = widget.Get <LabelWidget>("ADMIN");
            var adminFont = Game.Renderer.Fonts[admin.Font];

            var latency = widget.GetOrNull <LabelWidget>("LATENCY");

            if (latency != null)
            {
                latencyFont = Game.Renderer.Fonts[latency.Font];
            }

            var latencyPrefix = widget.GetOrNull <LabelWidget>("LATENCY_PREFIX");

            if (latencyPrefix != null)
            {
                latencyPrefixFont = Game.Renderer.Fonts[latencyPrefix.Font];
            }

            var ip          = widget.Get <LabelWidget>("IP");
            var addressFont = Game.Renderer.Fonts[ip.Font];

            var location     = widget.Get <LabelWidget>("LOCATION");
            var locationFont = Game.Renderer.Fonts[location.Font];

            var locationOffset = location.Bounds.Y;
            var addressOffset  = ip.Bounds.Y;
            var latencyOffset  = latency == null ? 0 : latency.Bounds.Y;
            var tooltipHeight  = widget.Bounds.Height;

            var margin = widget.Bounds.Width;

            widget.IsVisible = () => (orderManager.LobbyInfo.ClientWithIndex(clientIndex) != null);
            tooltipContainer.BeforeRender = () =>
            {
                if (!widget.IsVisible())
                {
                    return;
                }

                var latencyPrefixSize = latencyPrefix == null ? 0 : latencyPrefix.Bounds.X + latencyPrefixFont.Measure(latencyPrefix.GetText() + " ").X;
                var locationWidth     = locationFont.Measure(location.GetText()).X;
                var adminWidth        = adminFont.Measure(admin.GetText()).X;
                var addressWidth      = addressFont.Measure(ip.GetText()).X;
                var latencyWidth      = latencyFont == null ? 0 : latencyPrefixSize + latencyFont.Measure(latency.GetText()).X;
                var width             = Math.Max(locationWidth, Math.Max(adminWidth, Math.Max(addressWidth, latencyWidth)));
                widget.Bounds.Width = width + 2 * margin;
                if (latency != null)
                {
                    latency.Bounds.Width = widget.Bounds.Width;
                }
                ip.Bounds.Width       = widget.Bounds.Width;
                admin.Bounds.Width    = widget.Bounds.Width;
                location.Bounds.Width = widget.Bounds.Width;

                ip.Bounds.Y = addressOffset;
                if (latency != null)
                {
                    latency.Bounds.Y = latencyOffset;
                }
                location.Bounds.Y    = locationOffset;
                widget.Bounds.Height = tooltipHeight;

                if (admin.IsVisible())
                {
                    ip.Bounds.Y += admin.Bounds.Height;
                    if (latency != null)
                    {
                        latency.Bounds.Y += admin.Bounds.Height;
                    }
                    location.Bounds.Y    += admin.Bounds.Height;
                    widget.Bounds.Height += admin.Bounds.Height;
                }

                if (latencyPrefix != null)
                {
                    latencyPrefix.Bounds.Y = latency.Bounds.Y;
                }
                if (latency != null)
                {
                    latency.Bounds.X = latencyPrefixSize;
                }
            };

            admin.IsVisible = () => orderManager.LobbyInfo.ClientWithIndex(clientIndex).IsAdmin;
            var client = orderManager.LobbyInfo.ClientWithIndex(clientIndex);
            var ping   = orderManager.LobbyInfo.PingFromClient(client);

            if (latency != null)
            {
                latency.GetText  = () => LobbyUtils.LatencyDescription(ping);
                latency.GetColor = () => LobbyUtils.LatencyColor(ping);
            }

            var address             = LobbyUtils.GetExternalIP(clientIndex, orderManager);
            var cachedDescriptiveIP = LobbyUtils.DescriptiveIpAddress(address);

            ip.GetText = () => cachedDescriptiveIP;
            var cachedCountryLookup = GeoIP.LookupCountry(address);

            location.GetText = () => cachedCountryLookup;
        }
Example #5
0
        void RefreshServerListInner(List <GameServer> games)
        {
            if (games == null)
            {
                return;
            }

            var mods = games.GroupBy(g => g.Mods)
                       .OrderByDescending(g => GroupSortOrder(g.First()))
                       .ThenByDescending(g => g.Count());

            ScrollItemWidget nextServerRow = null;
            var rows = new List <Widget>();

            foreach (var modGames in mods)
            {
                if (modGames.All(Filtered))
                {
                    continue;
                }

                var header = ScrollItemWidget.Setup(headerTemplate, () => true, () => { });

                var headerTitle = modGames.First().ModLabel;
                header.Get <LabelWidget>("LABEL").GetText = () => headerTitle;
                rows.Add(header);

                Func <GameServer, int> listOrder = g =>
                {
                    // Servers waiting for players are always first
                    if (g.State == (int)ServerState.WaitingPlayers && g.Players > 0)
                    {
                        return(0);
                    }

                    // Then servers with spectators
                    if (g.State == (int)ServerState.WaitingPlayers && g.Spectators > 0)
                    {
                        return(1);
                    }

                    // Then active games
                    if (g.State >= (int)ServerState.GameStarted)
                    {
                        return(2);
                    }

                    // Empty servers are shown at the end because a flood of empty servers
                    // at the top of the game list make the community look dead
                    return(3);
                };

                foreach (var modGamesByState in modGames.GroupBy(listOrder).OrderBy(g => g.Key))
                {
                    // Sort 'Playing' games by Started, others by number of players
                    foreach (var game in modGamesByState.Key == 2 ? modGamesByState.OrderByDescending(g => g.Started) : modGamesByState.OrderByDescending(g => g.Players))
                    {
                        if (Filtered(game))
                        {
                            continue;
                        }

                        var canJoin = game.IsJoinable;
                        var item    = ScrollItemWidget.Setup(serverTemplate, () => currentServer == game, () => SelectServer(game), () => Join(game));
                        var title   = item.GetOrNull <LabelWidget>("TITLE");
                        if (title != null)
                        {
                            var font  = Game.Renderer.Fonts[title.Font];
                            var label = WidgetUtils.TruncateText(game.Name, title.Bounds.Width, font);
                            title.GetText  = () => label;
                            title.GetColor = () => canJoin ? title.TextColor : incompatibleGameColor;
                        }

                        var password = item.GetOrNull <ImageWidget>("PASSWORD_PROTECTED");
                        if (password != null)
                        {
                            password.IsVisible    = () => game.Protected;
                            password.GetImageName = () => canJoin ? "protected" : "protected-disabled";
                        }

                        var players = item.GetOrNull <LabelWidget>("PLAYERS");
                        if (players != null)
                        {
                            players.GetText = () => "{0} / {1}".F(game.Players, game.MaxPlayers)
                                              + (game.Spectators > 0 ? " + {0}".F(game.Spectators) : "");

                            players.GetColor = () => canJoin ? players.TextColor : incompatibleGameColor;
                        }

                        var state = item.GetOrNull <LabelWidget>("STATUS");
                        if (state != null)
                        {
                            var label = game.State >= (int)ServerState.GameStarted ?
                                        "Playing" : "Waiting";
                            state.GetText = () => label;

                            var color = GetStateColor(game, state, !canJoin);
                            state.GetColor = () => color;
                        }

                        var location = item.GetOrNull <LabelWidget>("LOCATION");
                        if (location != null)
                        {
                            var font = Game.Renderer.Fonts[location.Font];
                            var cachedServerLocation = game.Id != -1 ? GeoIP.LookupCountry(game.Address.Split(':')[0]) : "Local Network";
                            var label = WidgetUtils.TruncateText(cachedServerLocation, location.Bounds.Width, font);
                            location.GetText  = () => label;
                            location.GetColor = () => canJoin ? location.TextColor : incompatibleGameColor;
                        }

                        if (currentServer != null && game.Address == currentServer.Address)
                        {
                            nextServerRow = item;
                        }

                        rows.Add(item);
                    }
                }
            }

            Game.RunAfterTick(() =>
            {
                serverList.RemoveChildren();
                SelectServer(null);

                if (games == null)
                {
                    searchStatus = SearchStatus.Failed;
                    return;
                }

                if (!rows.Any())
                {
                    searchStatus = SearchStatus.NoGames;
                    return;
                }

                searchStatus = SearchStatus.Hidden;

                // Search for any unknown maps
                if (Game.Settings.Game.AllowDownloading)
                {
                    modData.MapCache.QueryRemoteMapDetails(services.MapRepository, games.Where(g => !Filtered(g)).Select(g => g.Map));
                }

                foreach (var row in rows)
                {
                    serverList.AddChild(row);
                }

                if (nextServerRow != null)
                {
                    nextServerRow.OnClick();
                }
            });
        }
Example #6
0
        void RefreshServerListInner(IEnumerable <GameServer> games)
        {
            if (games == null)
            {
                return;
            }

            var mods = games.GroupBy(g => g.Mods)
                       .OrderByDescending(g => GroupSortOrder(g.First()))
                       .ThenByDescending(g => g.Count());

            ScrollItemWidget nextServerRow = null;
            var rows = new List <Widget>();

            foreach (var modGames in mods)
            {
                if (modGames.All(Filtered))
                {
                    continue;
                }

                var header = ScrollItemWidget.Setup(headerTemplate, () => true, () => { });

                var headerTitle = modGames.First().ModLabel;
                header.Get <LabelWidget>("LABEL").GetText = () => headerTitle;
                rows.Add(header);

                foreach (var loop in modGames.OrderByDescending(g => g.IsJoinable).ThenByDescending(g => g.Players))
                {
                    var game = loop;
                    if (game == null || Filtered(game))
                    {
                        continue;
                    }

                    var canJoin = game.IsJoinable;
                    var item    = ScrollItemWidget.Setup(serverTemplate, () => currentServer == game, () => SelectServer(game), () => Join(game));
                    var title   = item.GetOrNull <LabelWidget>("TITLE");
                    if (title != null)
                    {
                        var font  = Game.Renderer.Fonts[title.Font];
                        var label = WidgetUtils.TruncateText(game.Name, title.Bounds.Width, font);
                        title.GetText  = () => label;
                        title.GetColor = () => canJoin ? title.TextColor : incompatibleGameColor;
                    }

                    var password = item.GetOrNull <ImageWidget>("PASSWORD_PROTECTED");
                    if (password != null)
                    {
                        password.IsVisible    = () => game.Protected;
                        password.GetImageName = () => canJoin ? "protected" : "protected-disabled";
                    }

                    var players = item.GetOrNull <LabelWidget>("PLAYERS");
                    if (players != null)
                    {
                        players.GetText = () => "{0} / {1}".F(game.Players, game.MaxPlayers)
                                          + (game.Spectators > 0 ? " + {0}".F(game.Spectators) : "");

                        players.GetColor = () => canJoin ? players.TextColor : incompatibleGameColor;
                    }

                    var state = item.GetOrNull <LabelWidget>("STATUS");
                    if (state != null)
                    {
                        var label = game.State >= (int)ServerState.GameStarted ?
                                    "Playing" : "Waiting";
                        state.GetText = () => label;

                        var color = GetStateColor(game, state, !canJoin);
                        state.GetColor = () => color;
                    }

                    var location = item.GetOrNull <LabelWidget>("LOCATION");
                    if (location != null)
                    {
                        var cachedServerLocation = GeoIP.LookupCountry(game.Address.Split(':')[0]);
                        location.GetText  = () => cachedServerLocation;
                        location.GetColor = () => canJoin ? location.TextColor : incompatibleGameColor;
                    }

                    if (currentServer != null && game.Address == currentServer.Address)
                    {
                        nextServerRow = item;
                    }

                    rows.Add(item);
                }
            }

            Game.RunAfterTick(() =>
            {
                serverList.RemoveChildren();
                SelectServer(null);

                if (games == null)
                {
                    searchStatus = SearchStatus.Failed;
                    return;
                }

                if (!rows.Any())
                {
                    searchStatus = SearchStatus.NoGames;
                    return;
                }

                searchStatus = SearchStatus.Hidden;

                // Search for any unknown maps
                if (Game.Settings.Game.AllowDownloading)
                {
                    Game.ModData.MapCache.QueryRemoteMapDetails(games.Where(g => !Filtered(g)).Select(g => g.Map));
                }

                foreach (var row in rows)
                {
                    serverList.AddChild(row);
                }

                if (nextServerRow != null)
                {
                    nextServerRow.OnClick();
                }
            });
        }
Example #7
0
        void RefreshServerListInner(IEnumerable <GameServer> games)
        {
            if (games == null)
            {
                return;
            }

            var mods = games.GroupBy(g => g.Mods)
                       .OrderByDescending(g => GroupSortOrder(g.First()))
                       .ThenByDescending(g => g.Count());

            var rows = new List <Widget>();

            foreach (var modGames in mods)
            {
                if (modGames.All(Filtered))
                {
                    continue;
                }

                var header = ScrollItemWidget.Setup(headerTemplate, () => true, () => { });

                var headerTitle = modGames.First().ModLabel;
                header.Get <LabelWidget>("LABEL").GetText = () => headerTitle;
                rows.Add(header);

                foreach (var loop in modGames.OrderByDescending(g => g.IsJoinable).ThenByDescending(g => g.Players))
                {
                    var game = loop;
                    if (game == null || Filtered(game))
                    {
                        continue;
                    }

                    var canJoin    = game.IsJoinable;
                    var compatible = game.IsCompatible;

                    var item = ScrollItemWidget.Setup(serverTemplate, () => currentServer == game, () => currentServer = game, () => Join(game));

                    var map     = Game.ModData.MapCache[game.Map];
                    var preview = item.GetOrNull <MapPreviewWidget>("MAP_PREVIEW");
                    if (preview != null)
                    {
                        preview.Preview = () => map;
                    }

                    var title = item.GetOrNull <LabelWidget>("TITLE");
                    if (title != null)
                    {
                        title.GetText  = () => game.Name;
                        title.GetColor = () => !compatible ? incompatibleGameColor : !canJoin ? cantJoinGameColor : title.TextColor;
                    }

                    var maptitle = item.GetOrNull <LabelWidget>("MAP");
                    if (maptitle != null)
                    {
                        maptitle.GetText  = () => map.Title;
                        maptitle.GetColor = () => !compatible ? Color.DarkGray : !canJoin ? Color.LightGray : maptitle.TextColor;
                    }

                    var players = item.GetOrNull <LabelWidget>("PLAYERS");
                    if (players != null)
                    {
                        players.GetText = () => "{0} / {1}".F(game.Players, game.MaxPlayers)
                                          + (game.Spectators > 0 ? "  ({0} Spectator{1})".F(game.Spectators, game.Spectators > 1 ? "s" : "") : "");
                        players.GetColor = () => !compatible ? incompatibleGameColor : !canJoin ? cantJoinGameColor : players.TextColor;
                    }

                    var state = item.GetOrNull <LabelWidget>("STATE");
                    if (state != null)
                    {
                        state.GetText  = () => GetStateLabel(game);
                        state.GetColor = () => GetStateColor(game, state, !compatible || !canJoin);
                    }

                    var ip = item.GetOrNull <LabelWidget>("IP");
                    if (ip != null)
                    {
                        ip.GetText  = () => game.Address;
                        ip.GetColor = () => !compatible ? incompatibleGameColor : !canJoin ? cantJoinGameColor : ip.TextColor;
                    }

                    var location = item.GetOrNull <LabelWidget>("LOCATION");
                    if (location != null)
                    {
                        var cachedServerLocation = GeoIP.LookupCountry(game.Address.Split(':')[0]);
                        location.GetText  = () => cachedServerLocation;
                        location.GetColor = () => !compatible ? incompatibleGameColor : !canJoin ? cantJoinGameColor : location.TextColor;
                    }

                    rows.Add(item);
                }
            }

            Game.RunAfterTick(() =>
            {
                serverList.RemoveChildren();
                currentServer = null;

                if (games == null)
                {
                    searchStatus = SearchStatus.Failed;
                    return;
                }

                if (!games.Any())
                {
                    searchStatus = SearchStatus.NoGames;
                    return;
                }

                currentServer = games.FirstOrDefault();
                searchStatus  = SearchStatus.Hidden;

                // Search for any unknown maps
                if (Game.Settings.Game.AllowDownloading)
                {
                    Game.ModData.MapCache.QueryRemoteMapDetails(games.Where(g => !Filtered(g)).Select(g => g.Map));
                }

                foreach (var row in rows)
                {
                    serverList.AddChild(row);
                }
            });
        }