diff --git a/src/main/java/me/braydon/mc/common/JavaMinecraftVersion.java b/src/main/java/me/braydon/mc/common/JavaMinecraftVersion.java index e387e39..cbfa908 100644 --- a/src/main/java/me/braydon/mc/common/JavaMinecraftVersion.java +++ b/src/main/java/me/braydon/mc/common/JavaMinecraftVersion.java @@ -24,6 +24,7 @@ package me.braydon.mc.common; import lombok.Getter; +import lombok.NonNull; import lombok.RequiredArgsConstructor; import lombok.ToString; @@ -108,7 +109,9 @@ public enum JavaMinecraftVersion { public static final JavaMinecraftVersion FROSTBURN_UPDATE = JavaMinecraftVersion.V1_10; public static final JavaMinecraftVersion THE_COMBAT_UPDATE = JavaMinecraftVersion.V1_9; public static final JavaMinecraftVersion BOUNTIFUL_UPDATE = JavaMinecraftVersion.V1_8; - + + private static final JavaMinecraftVersion[] VALUES = JavaMinecraftVersion.values(); + /** * The protocol number of this version. */ @@ -143,7 +146,17 @@ public enum JavaMinecraftVersion { } return this.name; } - + + /** + * Get the minimum Minecraft version. + * + * @return the minimum version + */ + @NonNull + public static JavaMinecraftVersion getMinimumVersion() { + return VALUES[VALUES.length - 2]; + } + /** * Get the version from the given protocol. * diff --git a/src/main/java/me/braydon/mc/model/MinecraftServer.java b/src/main/java/me/braydon/mc/model/MinecraftServer.java index d999feb..fdda300 100644 --- a/src/main/java/me/braydon/mc/model/MinecraftServer.java +++ b/src/main/java/me/braydon/mc/model/MinecraftServer.java @@ -25,11 +25,14 @@ package me.braydon.mc.model; import lombok.*; import me.braydon.mc.common.ColorUtils; +import me.braydon.mc.model.token.JavaServerStatusToken; import me.braydon.mc.service.pinger.MinecraftServerPinger; import me.braydon.mc.service.pinger.impl.BedrockMinecraftServerPinger; import me.braydon.mc.service.pinger.impl.JavaMinecraftServerPinger; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import java.util.UUID; /** @@ -84,6 +87,24 @@ public class MinecraftServer { */ private final Sample[] sample; + /** + * Create new player count data from a token. + * + * @param token the token to create from + * @return the player count data + */ + @NonNull + public static Players create(@NonNull JavaServerStatusToken.Players token) { + List samples = null; + if (token.getSample() != null) { + samples = new ArrayList<>(); // The player samples + for (JavaServerStatusToken.Players.Sample sample : token.getSample()) { + samples.add(new Sample(sample.getId(), Sample.Name.create(sample.getName()))); + } + } + return new Players(token.getOnline(), token.getMax(), samples != null ? samples.toArray(new Sample[0]) : null); + } + /** * A sample player. */ @@ -97,7 +118,39 @@ public class MinecraftServer { /** * The name of this player. */ - @NonNull private final String name; + @NonNull private final Name name; + + /** + * The name of a sample player. + */ + @AllArgsConstructor @Getter @ToString + public static class Name { + /** + * The raw name. + */ + @NonNull private final String raw; + + /** + * The clean name (no color codes). + */ + @NonNull private final String clean; + + /** + * The HTML name. + */ + @NonNull private final String html; + + /** + * Create a new name from a raw string. + * + * @param raw the raw name string + * @return the new name + */ + @NonNull + public static Name create(@NonNull String raw) { + return new Name(raw, ColorUtils.stripColor(raw), ColorUtils.toHTML(raw)); + } + } } } diff --git a/src/main/java/me/braydon/mc/model/server/JavaMinecraftServer.java b/src/main/java/me/braydon/mc/model/server/JavaMinecraftServer.java index e88e713..743f017 100644 --- a/src/main/java/me/braydon/mc/model/server/JavaMinecraftServer.java +++ b/src/main/java/me/braydon/mc/model/server/JavaMinecraftServer.java @@ -52,9 +52,27 @@ public final class JavaMinecraftServer extends MinecraftServer { /** * The Forge mod information for this server, null if none. + *

+ * This is for servers on 1.12 or below. + *

*/ private final ModInfo modInfo; + /** + * The Forge mod information for this server, null if none. + *

+ * This is for servers on 1.13 and above. + *

+ */ + private final ForgeData forgeData; + + /** + * Does this server preview chat? + * + * @see This for more + */ + private final boolean previewsChat; + /** * Does this server enforce secure chat? */ @@ -80,11 +98,13 @@ public final class JavaMinecraftServer extends MinecraftServer { private JavaMinecraftServer(@NonNull String hostname, String ip, int port, @NonNull Version version, @NonNull Players players, @NonNull MOTD motd, Favicon favicon, ModInfo modInfo, - boolean enforcesSecureChat, boolean preventsChatReports, boolean mojangBanned) { + ForgeData forgeData, boolean previewsChat, boolean enforcesSecureChat, boolean preventsChatReports, boolean mojangBanned) { super(hostname, ip, port, players, motd); this.version = version; this.favicon = favicon; this.modInfo = modInfo; + this.forgeData = forgeData; + this.previewsChat = previewsChat; this.enforcesSecureChat = enforcesSecureChat; this.preventsChatReports = preventsChatReports; this.mojangBanned = mojangBanned; @@ -105,9 +125,9 @@ public final class JavaMinecraftServer extends MinecraftServer { if (motdString == null) { // Not a string motd, convert from Json motdString = new TextComponent(ComponentSerializer.parse(AppConfig.GSON.toJson(token.getDescription()))).toLegacyText(); } - return new JavaMinecraftServer(hostname, ip, port, token.getVersion().detailedCopy(), token.getPlayers(), - MOTD.create(motdString), Favicon.create(token.getFavicon(), hostname), token.getModInfo(), - token.isEnforcesSecureChat(), token.isPreventsChatReports(), false + return new JavaMinecraftServer(hostname, ip, port, token.getVersion().detailedCopy(), Players.create(token.getPlayers()), + MOTD.create(motdString), Favicon.create(token.getFavicon(), hostname), token.getModInfo(), token.getForgeData(), + token.isPreviewsChat(), token.isEnforcesSecureChat(), token.isPreventsChatReports(), false ); } @@ -131,6 +151,11 @@ public final class JavaMinecraftServer extends MinecraftServer { */ private final int protocol; + /** + * A list of versions supported by this server. + */ + private final int[] supportedVersions; + /** * The name of the version for the protocol, null if unknown. */ @@ -152,7 +177,7 @@ public final class JavaMinecraftServer extends MinecraftServer { } } JavaMinecraftVersion minecraftVersion = JavaMinecraftVersion.byProtocol(protocol); - return new Version(name, platform, protocol, minecraftVersion == null ? null : minecraftVersion.getName()); + return new Version(name, platform, protocol, supportedVersions, minecraftVersion == null ? null : minecraftVersion.getName()); } } @@ -191,6 +216,9 @@ public final class JavaMinecraftServer extends MinecraftServer { /** * Forge mod information for a server. + *

+ * This is for servers on 1.12 or below. + *

*/ @AllArgsConstructor @Getter @ToString public static class ModInfo { @@ -202,22 +230,92 @@ public final class JavaMinecraftServer extends MinecraftServer { /** * The list of mods on this server, null or empty if none. */ - private final ForgeMod[] modList; + @SerializedName("modList") private final Mod[] mods; + + /** + * A Forge mod for a server. + */ + @AllArgsConstructor @Getter @ToString + private static class Mod { + /** + * The id of this mod. + */ + @NonNull @SerializedName("modid") private final String id; + + /** + * The version of this mod. + */ + private final String version; + } } /** - * A forge mod for a server. + * Forge information for a server. + *

+ * This is for servers on 1.13 and above. + *

*/ @AllArgsConstructor @Getter @ToString - private static class ForgeMod { + public static class ForgeData { /** - * The id of this mod. + * The list of channels on this server, null or empty if none. */ - @NonNull @SerializedName("modid") private final String id; + private final Channel[] channels; /** - * The version of this mod. + * The list of mods on this server, null or empty if none. */ - private final String version; + private final Mod[] mods; + + /** + * The version of the FML network. + */ + private final int fmlNetworkVersion; + + /** + * Are the channel and mod lists truncated? + *

+ * Legacy versions see truncated lists, modern + * versions ignore this truncated flag. + *

+ */ + private final boolean truncated; + + /** + * A Forge channel for a server. + */ + @AllArgsConstructor @Getter @ToString + private static class Channel { + /** + * The name of this channel. + */ + @NonNull @SerializedName("res") private final String name; + + /** + * The version of this channel. + */ + @NonNull private final String version; + + /** + * Whether this channel is required. + */ + private final boolean required; + } + + /** + * A Forge mod for a server. + */ + @AllArgsConstructor @Getter @ToString + private static class Mod { + /** + * The id of this mod. + */ + @NonNull @SerializedName("modId") private final String name; + + /** + * The marker for this mod. + */ + @NonNull @SerializedName("modmarker") private final String marker; + } } } \ No newline at end of file diff --git a/src/main/java/me/braydon/mc/model/token/JavaServerStatusToken.java b/src/main/java/me/braydon/mc/model/token/JavaServerStatusToken.java index faa09d6..95c050d 100644 --- a/src/main/java/me/braydon/mc/model/token/JavaServerStatusToken.java +++ b/src/main/java/me/braydon/mc/model/token/JavaServerStatusToken.java @@ -28,9 +28,10 @@ import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NonNull; import lombok.ToString; -import me.braydon.mc.model.MinecraftServer; import me.braydon.mc.model.server.JavaMinecraftServer; +import java.util.UUID; + /** * A token representing the response from * pinging a {@link JavaMinecraftServer}. @@ -60,13 +61,31 @@ public final class JavaServerStatusToken { /** * The player counts of this server. */ - @NonNull private final MinecraftServer.Players players; + @NonNull private final Players players; /** * The Forge mod information for this server, null if none. + *

+ * This is for servers on 1.12 or below. + *

*/ @SerializedName("modinfo") private final JavaMinecraftServer.ModInfo modInfo; + /** + * The Forge mod information for this server, null if none. + *

+ * This is for servers on 1.13 and above. + *

+ */ + private final JavaMinecraftServer.ForgeData forgeData; + + /** + * Does this server preview chat? + * + * @see This for more + */ + private final boolean previewsChat; + /** * Does this server enforce secure chat? */ @@ -76,4 +95,41 @@ public final class JavaServerStatusToken { * Is this server preventing chat reports? */ private final boolean preventsChatReports; + + /** + * Player count data for a server. + */ + @AllArgsConstructor @Getter @ToString + public static class Players { + /** + * The online players on this server. + */ + private final int online; + + /** + * The maximum allowed players on this server. + */ + private final int max; + + /** + * A sample of players on this server, null or empty if no sample. + */ + private final Sample[] sample; + + /** + * A sample player. + */ + @AllArgsConstructor @Getter @ToString + public static class Sample { + /** + * The unique id of this player. + */ + @NonNull private final UUID id; + + /** + * The name of this player. + */ + @NonNull private final String name; + } + } } \ No newline at end of file diff --git a/src/main/java/me/braydon/mc/service/pinger/impl/JavaMinecraftServerPinger.java b/src/main/java/me/braydon/mc/service/pinger/impl/JavaMinecraftServerPinger.java index a06684b..3f376d2 100644 --- a/src/main/java/me/braydon/mc/service/pinger/impl/JavaMinecraftServerPinger.java +++ b/src/main/java/me/braydon/mc/service/pinger/impl/JavaMinecraftServerPinger.java @@ -26,6 +26,7 @@ package me.braydon.mc.service.pinger.impl; import lombok.NonNull; import lombok.extern.log4j.Log4j2; import me.braydon.mc.common.DNSUtils; +import me.braydon.mc.common.JavaMinecraftVersion; import me.braydon.mc.common.packet.impl.java.JavaPacketHandshakingInSetProtocol; import me.braydon.mc.common.packet.impl.java.JavaPacketStatusInStart; import me.braydon.mc.config.AppConfig; @@ -81,7 +82,8 @@ public final class JavaMinecraftServerPinger implements MinecraftServerPinger