diff --git a/pom.xml b/pom.xml
index c443c02..66896e4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
maunz-discord
Maunz
A multi-purpose Discord bot with a focus on Source server tracking
- r56
+ r57
https://github.com/Vauff/Maunz-Discord
Maunz-Discord
diff --git a/src/com/vauff/maunzdiscord/commands/Map.java b/src/com/vauff/maunzdiscord/commands/Map.java
index 817ef11..56d4d61 100644
--- a/src/com/vauff/maunzdiscord/commands/Map.java
+++ b/src/com/vauff/maunzdiscord/commands/Map.java
@@ -121,7 +121,7 @@ private void runCmd(DeferrableInteractionEvent event, User user, Document doc, b
return;
}
- String url = MapImages.getMapImageURL(doc.getString("lastMap"), serverDoc.getInteger("appId"));
+ String url = MapImages.getMapImageURL(doc.getString("lastMap"), serverDoc.getString("appId"));
String ipPort = serverDoc.getString("ip") + ":" + serverDoc.getInteger("port");
EmbedCreateSpec embed = EmbedCreateSpec.builder()
@@ -195,7 +195,7 @@ private void runCmd(DeferrableInteractionEvent event, User user, Document doc, b
if (!formattedMap.equals(""))
{
- String url = MapImages.getMapImageURL(formattedMap, serverDoc.getInteger("appId"));
+ String url = MapImages.getMapImageURL(formattedMap, serverDoc.getString("appId"));
String lastPlayed = "";
String firstPlayed = "";
diff --git a/src/com/vauff/maunzdiscord/commands/Players.java b/src/com/vauff/maunzdiscord/commands/Players.java
index 36c0b77..5dfea82 100644
--- a/src/com/vauff/maunzdiscord/commands/Players.java
+++ b/src/com/vauff/maunzdiscord/commands/Players.java
@@ -105,6 +105,12 @@ private void runCmd(DeferrableInteractionEvent event, User user, Document doc)
int numberOfPlayers = serverDoc.getList("players", String.class).size();
+ if (numberOfPlayers < 2 && serverDoc.getString("appId").equals("730_cs2"))
+ {
+ Util.editReply(event, "Players Online: **" + serverDoc.getString("playerCount") + "**\n\n**Note:** Counter-Strike 2 servers do not currently support querying player information");
+ return;
+ }
+
if (numberOfPlayers == 0)
{
Util.editReply(event, "There are currently no players online!");
diff --git a/src/com/vauff/maunzdiscord/commands/Servers.java b/src/com/vauff/maunzdiscord/commands/Servers.java
index da7518b..c9a5a64 100644
--- a/src/com/vauff/maunzdiscord/commands/Servers.java
+++ b/src/com/vauff/maunzdiscord/commands/Servers.java
@@ -289,7 +289,7 @@ private ObjectId getOrCreateServer(String ip, int port)
return id;
}
- Document server = new Document("enabled", true).append("ip", ip).append("port", port).append("appId", 0).append("name", "N/A").append("map", "N/A").append("timestamp", 0L).append("playerCount", "0/0").append("players", new ArrayList())
+ Document server = new Document("enabled", true).append("ip", ip).append("port", port).append("appId", "0").append("name", "N/A").append("map", "N/A").append("timestamp", 0L).append("playerCount", "0/0").append("players", new ArrayList())
.append("downtimeTimer", 0).append("failedConnectionsThreshold", 3).append("mapDatabase", new ArrayList());
return Main.mongoDatabase.getCollection("servers").insertOne(server).getInsertedId().asObjectId().getValue();
diff --git a/src/com/vauff/maunzdiscord/core/Main.java b/src/com/vauff/maunzdiscord/core/Main.java
index a62aa53..4f25030 100644
--- a/src/com/vauff/maunzdiscord/core/Main.java
+++ b/src/com/vauff/maunzdiscord/core/Main.java
@@ -33,7 +33,7 @@ public class Main
{
public static GatewayDiscordClient gateway;
public static MongoDatabase mongoDatabase;
- public static String version = "r56";
+ public static String version = "r57";
public static Config cfg;
/**
diff --git a/src/com/vauff/maunzdiscord/servertracking/MapImageTimer.java b/src/com/vauff/maunzdiscord/servertracking/MapImageTimer.java
index 805baa3..dea0ede 100644
--- a/src/com/vauff/maunzdiscord/servertracking/MapImageTimer.java
+++ b/src/com/vauff/maunzdiscord/servertracking/MapImageTimer.java
@@ -64,16 +64,15 @@ public class MapImageTimer
Logger.log.debug("Map image API updated, rebuilding image list and clearing caches");
- for (String key : response.keySet())
+ for (String appId : response.keySet())
{
- if (!NumberUtils.isCreatable(key))
+ if (appId.equals("lastUpdated"))
continue;
ArrayList maps = new ArrayList<>();
- int appId = Integer.parseInt(key);
- for (int i = 0; i < response.getJSONArray(key).length(); i++)
- maps.add(response.getJSONArray(key).getString(i));
+ for (int i = 0; i < response.getJSONArray(appId).length(); i++)
+ maps.add(response.getJSONArray(appId).getString(i));
MapImages.mapImages.put(appId, maps);
MapImages.mapImageLookupCache.put(appId, new HashMap<>());
diff --git a/src/com/vauff/maunzdiscord/servertracking/MapImages.java b/src/com/vauff/maunzdiscord/servertracking/MapImages.java
index aa86f4c..52cd523 100644
--- a/src/com/vauff/maunzdiscord/servertracking/MapImages.java
+++ b/src/com/vauff/maunzdiscord/servertracking/MapImages.java
@@ -13,12 +13,12 @@ public class MapImages
/**
* Holds the latest image lists pulled from vauff.com
*/
- public static HashMap> mapImages = new HashMap<>();
+ public static HashMap> mapImages = new HashMap<>();
/**
* Cached lookup results from Util#getMapImageURL
*/
- public static HashMap> mapImageLookupCache = new HashMap<>();
+ public static HashMap> mapImageLookupCache = new HashMap<>();
/**
* Cached colour results from Util#averageColourFromURL
@@ -38,7 +38,7 @@ public class MapImages
* @param appId App ID of the game
* @return Image URL for the map, or "" on failure
*/
- public static String getMapImageURL(String map, int appId)
+ public static String getMapImageURL(String map, String appId)
{
// Force lower case since GameTracker does, and for an accurate levenshtein distance
String mapLower = map.toLowerCase();
@@ -88,7 +88,7 @@ public static Color getMapImageColour(String url) throws Exception
* @param appId App ID of the game
* @return Image URL for the map, or "" on failure
*/
- private static String getVauffMapImageURL(String map, int appId)
+ private static String getVauffMapImageURL(String map, String appId)
{
// As we accomodate for mapCharacterLimit, all image map names at vauff.com should never exceed 31 characters
String trimmedMap = StringUtils.substring(map, 0, 31);
@@ -124,94 +124,96 @@ private static String getVauffMapImageURL(String map, int appId)
* @param appId App ID of the game
* @return GameTracker's directory name for the given game
*/
- private static String appIdToGameTrackerName(int appId)
+ private static String appIdToGameTrackerName(String appId)
{
return switch (appId)
{
- case 10 -> "cs";
- case 20 -> "tfc";
- case 30 -> "dod";
- case 70 -> "hl";
- case 80 -> "czero";
- case 240 -> "css";
- case 300 -> "dods";
- case 320 -> "hl2dm";
- case 440 -> "tf2";
- case 500 -> "l4d";
- case 550 -> "left4dead2";
- case 570 -> "dota2";
- case 630 -> "alienswarm";
- case 730 -> "csgo";
- case 1200 -> "ror";
- case 1250 -> "killingfloor";
- case 1280 -> "rordh";
- case 2200 -> "q3";
- case 2210 -> "q4";
- case 2310 -> "qw";
- case 2320 -> "q2";
- case 2620 -> "cod";
- case 2630 -> "cod2";
- case 2640 -> "uo";
- case 4000 -> "garrysmod";
- case 4920 -> "ns2";
- case 6020 -> "swjk";
- case 6060 -> "swbf2";
- case 7940 -> "cod4";
- case 9010 -> "wolf";
- case 9050 -> "doom3";
- case 9460 -> "ffow";
- case 10000 -> "etqw";
- case 10090 -> "codww";
- case 13140 -> "aa3";
- case 13210 -> "ut3";
- case 13230 -> "ut2k4";
- case 13240 -> "ut";
- case 17300 -> "crysis";
- case 17330 -> "warhead";
- case 17500 -> "hl2zp";
- case 17700 -> "ins";
- case 21090 -> "fear";
- case 22350 -> "brink";
- case 24960 -> "bc2";
- case 33900 -> "arma2";
- case 35450 -> "ro2";
- case 42700 -> "blackops";
- case 47790 -> "moh";
- case 55100 -> "homefront";
- case 63200 -> "mnc";
- case 63380 -> "sniperelite2";
- case 65780 -> "arma";
- case 96300 -> "ravaged";
- case 107410 -> "arma3";
- case 108800 -> "crysis2";
- case 115300 -> "mw3";
- case 203290 -> "aapg";
- case 211820 -> "starbound";
- case 214630 -> "blackopsmac";
- case 221100 -> "dayz";
- case 222880 -> "insurgency2014";
- case 224580 -> "dayzmod";
- case 232090 -> "kf2";
- case 238430 -> "contagion";
- case 244850 -> "spaceengi";
- case 251570 -> "7daystodie";
- case 252490 -> "rust";
- case 253530 -> "ff";
- case 259080 -> "jc2";
- case 282440 -> "ql";
- case 290080 -> "lifyo";
- case 311210 -> "codbo3";
- case 346110 -> "arkse";
- case 393420 -> "hurtworld";
- case 440900 -> "conan";
- case 489940 -> "battalion1944";
- case 529180 -> "dnl";
- case 581320 -> "ins_sandstorm";
- case 659280 -> "urbanterror";
- case 1238820 -> "bf3";
- case 1238860 -> "bf4";
- case 1238880 -> "bfhl";
- case 1873030 -> "et";
+ case "10" -> "cs";
+ case "20" -> "tfc";
+ case "30" -> "dod";
+ case "70" -> "hl";
+ case "80" -> "czero";
+ case "240" -> "css";
+ case "300" -> "dods";
+ case "320" -> "hl2dm";
+ case "440" -> "tf2";
+ case "500" -> "l4d";
+ case "550" -> "left4dead2";
+ case "570" -> "dota2";
+ case "630" -> "alienswarm";
+ case "730_csgo" -> "csgo";
+ // TODO: Update this if GameTracker ever gets CS2 support
+ case "730_cs2" -> "csgo";
+ case "1200" -> "ror";
+ case "1250" -> "killingfloor";
+ case "1280" -> "rordh";
+ case "2200" -> "q3";
+ case "2210" -> "q4";
+ case "2310" -> "qw";
+ case "2320" -> "q2";
+ case "2620" -> "cod";
+ case "2630" -> "cod2";
+ case "2640" -> "uo";
+ case "4000" -> "garrysmod";
+ case "4920" -> "ns2";
+ case "6020" -> "swjk";
+ case "6060" -> "swbf2";
+ case "7940" -> "cod4";
+ case "9010" -> "wolf";
+ case "9050" -> "doom3";
+ case "9460" -> "ffow";
+ case "10000" -> "etqw";
+ case "10090" -> "codww";
+ case "13140" -> "aa3";
+ case "13210" -> "ut3";
+ case "13230" -> "ut2k4";
+ case "13240" -> "ut";
+ case "17300" -> "crysis";
+ case "17330" -> "warhead";
+ case "17500" -> "hl2zp";
+ case "17700" -> "ins";
+ case "21090" -> "fear";
+ case "22350" -> "brink";
+ case "24960" -> "bc2";
+ case "33900" -> "arma2";
+ case "35450" -> "ro2";
+ case "42700" -> "blackops";
+ case "47790" -> "moh";
+ case "55100" -> "homefront";
+ case "63200" -> "mnc";
+ case "63380" -> "sniperelite2";
+ case "65780" -> "arma";
+ case "96300" -> "ravaged";
+ case "107410" -> "arma3";
+ case "108800" -> "crysis2";
+ case "115300" -> "mw3";
+ case "203290" -> "aapg";
+ case "211820" -> "starbound";
+ case "214630" -> "blackopsmac";
+ case "221100" -> "dayz";
+ case "222880" -> "insurgency2014";
+ case "224580" -> "dayzmod";
+ case "232090" -> "kf2";
+ case "238430" -> "contagion";
+ case "244850" -> "spaceengi";
+ case "251570" -> "7daystodie";
+ case "252490" -> "rust";
+ case "253530" -> "ff";
+ case "259080" -> "jc2";
+ case "282440" -> "ql";
+ case "290080" -> "lifyo";
+ case "311210" -> "codbo3";
+ case "346110" -> "arkse";
+ case "393420" -> "hurtworld";
+ case "440900" -> "conan";
+ case "489940" -> "battalion1944";
+ case "529180" -> "dnl";
+ case "581320" -> "ins_sandstorm";
+ case "659280" -> "urbanterror";
+ case "1238820" -> "bf3";
+ case "1238860" -> "bf4";
+ case "1238880" -> "bfhl";
+ case "1873030" -> "et";
default -> "";
};
}
diff --git a/src/com/vauff/maunzdiscord/servertracking/ServerRequestThread.java b/src/com/vauff/maunzdiscord/servertracking/ServerRequestThread.java
index aa1a730..73bd526 100644
--- a/src/com/vauff/maunzdiscord/servertracking/ServerRequestThread.java
+++ b/src/com/vauff/maunzdiscord/servertracking/ServerRequestThread.java
@@ -77,10 +77,11 @@ public void run()
serverInfoSuccess = true;
}
+ // TODO: Remove this eventually when most CS:GO servers die, issue is not present in CS2 and isn't worth keeping for a few servers
// CS:GO servers by default use host_info_show 1 which uses a game-specific A2S_INFO implementation, only host_info_show 2 uses SteamWorks
// Unfortunately this implementation is incapable of providing a correct player count during a map change (returns 0), so we work around this by double-checking "empty" CS:GO servers are actually empty a little while after
// See https://github.com/perilouswithadollarsign/cstrike15_src/blob/master/engine/baseserver.cpp#L1261, GetNumPlayers() uses m_pUserInfoTable which is emptied during a map change
- if (doc.getInteger("appId") == 730 && server.getServerInfo().containsKey("numberOfPlayers") && !Objects.isNull(server.getServerInfo().get("numberOfPlayers")) && ((Byte) server.getServerInfo().get("numberOfPlayers")).intValue() == 0 && !retriedForCsgoPlayerCount)
+ if (doc.getString("appId").equals("730_csgo") && server.getServerInfo().containsKey("numberOfPlayers") && !Objects.isNull(server.getServerInfo().get("numberOfPlayers")) && ((Byte) server.getServerInfo().get("numberOfPlayers")).intValue() == 0 && !retriedForCsgoPlayerCount)
{
Thread.sleep(5000);
serverInfoSuccess = false;
@@ -131,7 +132,7 @@ public void run()
HashMap serverInfo = server.getServerInfo();
long timestamp = 0;
- int appId = 0;
+ String appId = "0";
String map = "";
String name = "N/A";
int currentPlayers = 0;
@@ -149,11 +150,31 @@ public void run()
// 24-bit app id within 64-bit game id, may not be available
if (serverInfo.containsKey("gameId") && !Objects.isNull(serverInfo.get("gameId")))
- appId = (int) (((long) serverInfo.get("gameId")) & (1L << 24) - 1L);
-
+ appId = String.valueOf((int) (((long) serverInfo.get("gameId")) & (1L << 24) - 1L));
// 16-bit app id, possibly truncated but (theoretically) always available
else if (serverInfo.containsKey("appId") && !Objects.isNull(serverInfo.get("appId")))
- appId = (short) serverInfo.get("appId");
+ appId = String.valueOf((short) serverInfo.get("appId"));
+
+ // Special handling for CS:GO/CS2, thanks for two games on the same app id, Valve!
+ if (appId.equals("730"))
+ {
+ if (serverInfo.containsKey("gameVersion") && !Objects.isNull(serverInfo.get("gameVersion")))
+ {
+ String version = serverInfo.get("gameVersion").toString();
+
+ // Strip periods, take first three numbers only e.g. "1.38.8.1" > 138
+ int majorVersion = Integer.parseInt(version.replace(".", "").substring(0, 3));
+
+ if (majorVersion >= 139)
+ appId = "730_cs2";
+ else if (majorVersion <= 138)
+ appId = "730_csgo";
+ }
+ else
+ {
+ appId = "0";
+ }
+ }
if (serverInfo.containsKey("serverName") && !Objects.isNull(serverInfo.get("serverName")))
name = serverInfo.get("serverName").toString();
@@ -201,7 +222,7 @@ else if (serverInfo.containsKey("appId") && !Objects.isNull(serverInfo.get("appI
}
}
- if (appId != 0 && appId != doc.getInteger("appId"))
+ if (!appId.equals("0") && !appId.equals(doc.getString("appId")))
Main.mongoDatabase.getCollection("servers").updateOne(eq("_id", id), new Document("$set", new Document("appId", appId)));
if (!playerCount.equals("") && !playerCount.equals(doc.getString("playerCount")))
diff --git a/src/com/vauff/maunzdiscord/servertracking/ServiceProcessThread.java b/src/com/vauff/maunzdiscord/servertracking/ServiceProcessThread.java
index 6473151..f501c1b 100644
--- a/src/com/vauff/maunzdiscord/servertracking/ServiceProcessThread.java
+++ b/src/com/vauff/maunzdiscord/servertracking/ServiceProcessThread.java
@@ -96,7 +96,7 @@ public void run()
if (!map.equals("") && !doc.getString("lastMap").equalsIgnoreCase(map))
{
- String url = MapImages.getMapImageURL(map, serverDoc.getInteger("appId"));
+ String url = MapImages.getMapImageURL(map, serverDoc.getString("appId"));
String ipPort = serverDoc.getString("ip") + ":" + serverDoc.getInteger("port");
EmbedCreateSpec embed = EmbedCreateSpec.builder()