public async Task <DataGameList> GetGamesNew() { Tuple <string, DateTime> gameData = await TryReadText(filePath, TimeSpan.FromSeconds(5)); if (gameData == null || string.IsNullOrWhiteSpace(gameData.Item1)) { return(null); } var LobbyData = JsonConvert.DeserializeObject <Dictionary <string, Lobby> >(gameData.Item1); //return new BZ98ServerData() //{ // Games = LobbyData.Where(dr => !dr.Value.isChat // && (!dr.Value.isPrivate || (dr.Value.isPrivate && dr.Value.IsPassworded == true)) // && ((!string.IsNullOrWhiteSpace(dr.Value.clientVersion)) && ("0123456789".Contains(dr.Value.clientVersion[0]))) // not mobile which starts with MB or something // && ((!string.IsNullOrWhiteSpace(dr.Value.clientVersion)) && (dr.Value.clientVersion != "0.0.0")) // not test game // ).Select(dr => dr.Value).ToList(), // Modified = gameData.Item2 //}; DataGameList data = new DataGameList() { GameTitle = this.Title, Header = new DataGameListHeader() { Description = "List of games currently on BZ98 Redux matchmaking server", Image = "http://discord.battlezone.report/resources/logos/bz98r.png", Credit = $"Fetched by Nielk1's BZ98Bridge Bot" } }; data.Header.ServerStatus = new DataGameListServerStatus[] { new DataGameListServerStatus() { Name = "Rebellion", Status = EDataGameListServerStatus.NotSet, Updated = gameData.Item2 } }; data.Games = (await Task.WhenAll( LobbyData .Where(dr => !dr.Value.isChat && (!dr.Value.isPrivate || (dr.Value.isPrivate && dr.Value.IsPassworded == true)) //&& ((!string.IsNullOrWhiteSpace(dr.Value.clientVersion)) && ("0123456789".Contains(dr.Value.clientVersion[0]))) // not mobile which starts with MB or something && ((!string.IsNullOrWhiteSpace(dr.Value.clientVersion)) && (dr.Value.clientVersion != "0.0.0")) // not test game ).Select(dr => dr.Value) .Select(async raw => { DataGameListGame game = new DataGameListGame(); game.Name = raw.Name; game.Image = await GetShellMap(raw.MapFile) ?? "http://discord.battlezone.report/resources/logos/nomap.png"; game.CurPlayers = raw.userCount; game.MaxPlayers = raw.PlayerLimit; if (raw.isLocked) { game.Status = EDataGameListServerGameStatus.Locked; } else if (raw.IsPassworded == true) { game.Status = EDataGameListServerGameStatus.Passworded; } else { game.Status = EDataGameListServerGameStatus.Open; } game.MapFilename = raw.MapFile; game.Footer = raw.MapFile + @".bzn"; if (!string.IsNullOrWhiteSpace(raw.clientVersion)) { game.Footer += $" <{raw.clientVersion}>"; } { await Task.WhenAll(raw.users .Select(async dr => { string team = dr.Value.metadata.ContainsKey("team") ? dr.Value.metadata["team"] : string.Empty; string vehicle = dr.Value.metadata.ContainsKey("vehicle") ? dr.Value.metadata["vehicle"] : string.Empty; int teamInt = 0; UserData userData = await GetUserData(dr.Value.id, dr.Value.authType); game.Players.Add(new DataGameListPlayer() { Index = int.TryParse(team, out teamInt) ? (int?)teamInt : null, Name = dr.Value.name, PlayerClass = vehicle, Url = userData?.ProfileUrl }); })); game.PlayersHeader = "Players"; } { ulong workshopIdNum = 0; if (!string.IsNullOrWhiteSpace(raw.WorkshopID) && raw.WorkshopID != "0") { if (ulong.TryParse(raw.WorkshopID, out workshopIdNum) && workshopIdNum > 0) { Task <string> modNameTask = Task.Run(async() => { string modNameRet = await _steam.GetSteamWorkshopName(raw.WorkshopID); return(modNameRet); }); var modName = modNameTask?.Result ?? raw.WorkshopID; if (!string.IsNullOrWhiteSpace(modName)) { game.TopInfo.Add($"Mod: [{Format.Sanitize(modName)}](http://steamcommunity.com/sharedfiles/filedetails/?id={raw.WorkshopID})"); } else { game.TopInfo.Add($"Mod: [{Format.Sanitize(raw.WorkshopID)}](http://steamcommunity.com/sharedfiles/filedetails/?id={raw.WorkshopID}"); } } else { game.TopInfo.Add("Mod: " + raw.WorkshopID); } } } game.Properties.Add(new Tuple <string, string>("Map", "[" + raw.MapFile + "]")); game.Properties.Add(new Tuple <string, string>("State", raw.IsEnded ? "Ended" : raw.IsLaunched ? "Launched" : "In Shell")); if (raw.TimeLimit.HasValue && raw.TimeLimit.Value > 0) { game.Properties.Add(new Tuple <string, string>("TimeLimit", raw.TimeLimit.Value.ToString())); } if (raw.KillLimit.HasValue && raw.KillLimit.Value > 0) { game.Properties.Add(new Tuple <string, string>("KillLimit", raw.KillLimit.Value.ToString())); } if (raw.Lives.HasValue && raw.Lives.Value > 0) { game.Properties.Add(new Tuple <string, string>("Lives", raw.Lives.Value.ToString())); } if (raw.SyncJoin.HasValue) { game.Properties.Add(new Tuple <string, string>("SyncJoin", raw.SyncJoin.Value ? "On" : "Off")); } if (raw.SatelliteEnabled.HasValue) { game.Properties.Add(new Tuple <string, string>("Satellite", raw.SatelliteEnabled.Value ? "On" : "Off")); } if (raw.BarracksEnabled.HasValue) { game.Properties.Add(new Tuple <string, string>("Barracks", raw.BarracksEnabled.Value ? "On" : "Off")); } if (raw.SniperEnabled.HasValue) { game.Properties.Add(new Tuple <string, string>("Sniper", raw.SniperEnabled.Value ? "On" : "Off")); } if (raw.SplinterEnabled.HasValue) { game.Properties.Add(new Tuple <string, string>("Splinter", raw.SplinterEnabled.Value ? "On" : "Off")); } return(game); }) )).ToArray(); return(data); }
public async Task <DataGameList> GetGamesNew() { using (var http = new HttpClient()) { var res = await http.GetStringAsync(queryUrl).ConfigureAwait(false); var gamelist = JsonConvert.DeserializeObject <BZCCRaknetData>(res); //gamelist.SetBz2Service(this); //return gamelist; DataGameList data = new DataGameList() { GameTitle = this.Title, Header = new DataGameListHeader() { Description = "List of games currently on Battlezone CC matchmaking servers", Image = "http://discord.battlezone.report/resources/logos/bzcc.png", Credit = "Brought to you by Nielk1's Raknet Bot" } }; { bool isOnIonDriver = gamelist.GET.Any(game => game.IsOnIonDriver()); DataGameListServerStatus IonDriverStatus = new DataGameListServerStatus() { Name = "IonDriver", Updated = null }; //if (isIonDriver) //{ // IonDriverStatus.Status = EDataGameListServerStatus.Online; //} //else if (isIonDriver) //{ // IonDriverStatus.Status = EDataGameListServerStatus.NoMarker; //} //else //{ // IonDriverStatus.Status = EDataGameListServerStatus.Unknown; //} IonDriverStatus.Status = EDataGameListServerStatus.NotSet; bool isOnRebellion = gamelist.GET.Any(game => game.IsOnRebellion()); bool haveRebellionStatus = gamelist.proxyStatus.ContainsKey("Rebellion"); bool isRebellionUp = haveRebellionStatus && gamelist.proxyStatus["Rebellion"].success == true; string statusRebellion = haveRebellionStatus ? gamelist.proxyStatus["Rebellion"].status : null; DateTime?dateRebellion = haveRebellionStatus ? gamelist.proxyStatus["Rebellion"].updated : null; DataGameListServerStatus RebellionStatus = new DataGameListServerStatus() { Name = "Rebellion (Primary)", Updated = dateRebellion }; if (isRebellionUp) { RebellionStatus.Status = EDataGameListServerStatus.Online; } else if (!isRebellionUp) { RebellionStatus.Status = EDataGameListServerStatus.Offline; } else { RebellionStatus.Status = EDataGameListServerStatus.Unknown; } data.Header.ServerStatus = new DataGameListServerStatus[] { IonDriverStatus, RebellionStatus }; } data.Games = (await Task.WhenAll( gamelist.GET .Select(async raw => { DataGameListGame game = new DataGameListGame(); game.Name = raw.Name; game.Image = "http://discord.battlezone.report/resources/logos/nomap.png"; game.CurPlayers = raw.CurPlayers; game.MaxPlayers = raw.MaxPlayers; if (raw.Locked) { game.Status = EDataGameListServerGameStatus.Locked; } else if (raw.Passworded) { game.Status = EDataGameListServerGameStatus.Passworded; } else if (!raw.MaxPlayers.HasValue) { game.Status = EDataGameListServerGameStatus.Unknown; } else { game.Status = EDataGameListServerGameStatus.Open; } game.MapFilename = raw.MapFile; game.Footer = raw.MapFile + @".bzn"; if (!string.IsNullOrWhiteSpace(raw.MOTD)) { game.TopInfo.Add(Format.Sanitize(raw.MOTD)); } foreach (string mod in raw.Mods) { ulong workshopIdNum = 0; if (!string.IsNullOrWhiteSpace(mod) && mod != "0") { if (ulong.TryParse(mod, out workshopIdNum) && workshopIdNum > 0) { Task <string> modNameTask = Task.Run(async() => { string modNameRet = await _steam.GetSteamWorkshopName(mod); return(modNameRet); }); var modName = modNameTask?.Result ?? mod; if (!string.IsNullOrWhiteSpace(modName)) { game.TopInfo.Add($"Mod: [{Format.Sanitize(modName)}](http://steamcommunity.com/sharedfiles/filedetails/?id={mod})"); } else { game.TopInfo.Add($"Mod: [{Format.Sanitize(mod)}](http://steamcommunity.com/sharedfiles/filedetails/?id={mod}"); } } else { game.TopInfo.Add("Mod: " + mod); } } break; // hack to only do the first entry until I properly redo this } { int k = 1; int d = 1; int s = 1; bool scoreNeedsSign = false; raw.pl.ForEach(dr => { k = Math.Max(k, (dr.Kills.HasValue ? dr.Kills.Value : 0).ToString().Length); d = Math.Max(d, (dr.Deaths.HasValue ? dr.Deaths.Value : 0).ToString().Length); s = Math.Max(s, Math.Abs(dr.Score.HasValue ? dr.Score.Value : 0).ToString().Length); scoreNeedsSign = scoreNeedsSign || (dr.Score < 0); }); await Task.WhenAll(raw.pl.Select(async dr => { int Killv = dr.Kills.HasValue ? dr.Kills.Value : 0; int Deathsv = dr.Deaths.HasValue ? dr.Deaths.Value : 0; int Scorev = dr.Score.HasValue ? dr.Score.Value : 0; string scoresign = "0"; if (Scorev > 0) { scoresign = "+"; } if (Scorev < 0) { scoresign = "-"; } if (!scoreNeedsSign) { scoresign = string.Empty; } UserData userData = await GetUserData(dr.PlayerID); game.Players.Add(new DataGameListPlayer() { Index = dr.Team, Name = dr.Name, PlayerClass = $"{Killv.ToString().PadLeft(k, '0')}/{Deathsv.ToString().PadLeft(d, '0')}/{scoresign}{Math.Abs(Scorev).ToString().PadLeft(s, '0')}", Url = userData?.ProfileUrl }); })); game.PlayersHeader = "[T] (K/D/S) Players"; } { string name = await GetBZCCGameProperty("name", raw.MapFile); if (string.IsNullOrWhiteSpace(name)) { game.Properties.Add(new Tuple <string, string>("Map", $"[{raw.MapFile}]")); } else { game.Properties.Add(new Tuple <string, string>("Map", $"{name}")); } if (!string.IsNullOrWhiteSpace(raw.v)) { game.Properties.Add(new Tuple <string, string>("Version", $"{raw.v}")); } /*if (!string.IsNullOrWhiteSpace(raw.d)) * { * game.Properties.Add(new Tuple<string, string>("Mod", $"[{raw.d}]")); * }*/ if (!string.IsNullOrWhiteSpace(raw.t)) { switch (raw.t) { case "0": game.Properties.Add(new Tuple <string, string>("NAT", $"NONE")); /// Works with anyone break; case "1": game.Properties.Add(new Tuple <string, string>("NAT", $"FULL CONE")); /// Accepts any datagrams to a port that has been previously used. Will accept the first datagram from the remote peer. break; case "2": game.Properties.Add(new Tuple <string, string>("NAT", $"ADDRESS RESTRICTED")); /// Accepts datagrams to a port as long as the datagram source IP address is a system we have already sent to. Will accept the first datagram if both systems send simultaneously. Otherwise, will accept the first datagram after we have sent one datagram. break; case "3": game.Properties.Add(new Tuple <string, string>("NAT", $"PORT RESTRICTED")); /// Same as address-restricted cone NAT, but we had to send to both the correct remote IP address and correct remote port. The same source address and port to a different destination uses the same mapping. break; case "4": game.Properties.Add(new Tuple <string, string>("NAT", $"SYMMETRIC")); /// A different port is chosen for every remote destination. The same source address and port to a different destination uses a different mapping. Since the port will be different, the first external punchthrough attempt will fail. For this to work it requires port-prediction (MAX_PREDICTIVE_PORT_RANGE>1) and that the router chooses ports sequentially. break; case "5": game.Properties.Add(new Tuple <string, string>("NAT", $"UNKNOWN")); /// Hasn't been determined. NATTypeDetectionClient does not use this, but other plugins might break; case "6": game.Properties.Add(new Tuple <string, string>("NAT", $"DETECTION IN PROGRESS")); /// In progress. NATTypeDetectionClient does not use this, but other plugins might break; case "7": game.Properties.Add(new Tuple <string, string>("NAT", $"SUPPORTS UPNP")); /// Didn't bother figuring it out, as we support UPNP, so it is equivalent to NAT_TYPE_NONE. NATTypeDetectionClient does not use this, but other plugins might break; default: game.Properties.Add(new Tuple <string, string>("NAT", $"[" + raw.t + "]")); break; } } switch (raw.proxySource) { case "Rebellion": game.Properties.Add(new Tuple <string, string>("List", $"Rebellion")); break; default: game.Properties.Add(new Tuple <string, string>("List", $"IonDriver")); break; } { switch (raw.GameType) { case 0: game.Properties.Add(new Tuple <string, string>("Type", $"All")); break; case 1: switch (raw.GameSubType) { case 0: game.Properties.Add(new Tuple <string, string>("Type", $"DM")); break; case 1: game.Properties.Add(new Tuple <string, string>("Type", $"KOTH")); break; case 2: game.Properties.Add(new Tuple <string, string>("Type", $"CTF")); break; case 3: game.Properties.Add(new Tuple <string, string>("Type", $"Loot")); break; case 4: game.Properties.Add(new Tuple <string, string>("Type", $"DM [RESERVED]")); break; case 5: game.Properties.Add(new Tuple <string, string>("Type", $"Race")); break; case 6: game.Properties.Add(new Tuple <string, string>("Type", $"Race (Vehicle Only)")); break; case 7: game.Properties.Add(new Tuple <string, string>("Type", $"DM (Vehicle Only)")); break; default: game.Properties.Add(new Tuple <string, string>("Type", $"DM [UNKNOWN {raw.GameSubType}]")); break; } break; case 2: switch (raw.GameSubType) { case 12: game.Properties.Add(new Tuple <string, string>("Type", $"STRAT")); break; case 13: case 41: game.Properties.Add(new Tuple <string, string>("Type", $"MPI")); break; default: game.Properties.Add(new Tuple <string, string>("Type", $"STRAT [UNKNOWN {raw.GameSubType}]")); break; } break; case 3: game.Properties.Add(new Tuple <string, string>("Type", $"MPI [Invalid]")); break; } if (raw.GameTimeMinutes.HasValue) { switch (raw.ServerInfoMode) { case 1: if (raw.GameTimeMinutes.Value == 255) { game.Properties.Add(new Tuple <string, string>("Time", $"Not playing or in shell")); } else { game.Properties.Add(new Tuple <string, string>("Time", $"Not playing or in shell for {raw.GameTimeMinutes.Value} minutes")); } break; case 3: game.Properties.Add(new Tuple <string, string>("Time", $"Playing for {raw.GameTimeMinutes.Value} minutes")); break; } } if (raw.TPS.HasValue && raw.TPS > 0) { game.Properties.Add(new Tuple <string, string>("TPS", $"{raw.TPS}")); } if (raw.MaxPing.HasValue && raw.MaxPing > 0) { game.Properties.Add(new Tuple <string, string>("MaxPing", $"{raw.MaxPing}")); } if (raw.TimeLimit.HasValue && raw.TimeLimit > 0) { game.Properties.Add(new Tuple <string, string>("TimeLim", $"{raw.TimeLimit}")); } if (raw.KillLimit.HasValue && raw.KillLimit > 0) { game.Properties.Add(new Tuple <string, string>("KillLim", $"{raw.KillLimit}")); } } } return(game); }))).ToArray(); return(data); } }