diff options
Diffstat (limited to 'patches/api/0168-Add-GS4-Query-event.patch')
-rw-r--r-- | patches/api/0168-Add-GS4-Query-event.patch | 436 |
1 files changed, 436 insertions, 0 deletions
diff --git a/patches/api/0168-Add-GS4-Query-event.patch b/patches/api/0168-Add-GS4-Query-event.patch new file mode 100644 index 0000000000..a153279317 --- /dev/null +++ b/patches/api/0168-Add-GS4-Query-event.patch @@ -0,0 +1,436 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mark Vainomaa <[email protected]> +Date: Sun, 17 Mar 2019 21:46:27 +0200 +Subject: [PATCH] Add GS4 Query event + + +diff --git a/src/main/java/com/destroystokyo/paper/event/server/GS4QueryEvent.java b/src/main/java/com/destroystokyo/paper/event/server/GS4QueryEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..8edc33bde29e967cec488d0f5e2f1097291978a6 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/server/GS4QueryEvent.java +@@ -0,0 +1,424 @@ ++package com.destroystokyo.paper.event.server; ++ ++import com.google.common.base.Preconditions; ++import com.google.common.collect.ImmutableList; ++import org.bukkit.Server; ++import org.bukkit.event.Event; ++import org.bukkit.event.HandlerList; ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.NotNull; ++ ++import java.net.InetAddress; ++import java.util.ArrayList; ++import java.util.Arrays; ++import java.util.Collection; ++import java.util.List; ++ ++/** ++ * This event is fired if server is getting queried over GS4 Query protocol. ++ * <br> ++ * Adapted from Velocity's ProxyQueryEvent ++ * ++ * @author Mark Vainomaa ++ */ ++public final class GS4QueryEvent extends Event { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private final QueryType queryType; ++ private final InetAddress querierAddress; ++ private QueryResponse response; ++ ++ @ApiStatus.Internal ++ public GS4QueryEvent(@NotNull QueryType queryType, @NotNull InetAddress querierAddress, @NotNull QueryResponse response) { ++ super(true); // should always be called async ++ this.queryType = queryType; ++ this.querierAddress = querierAddress; ++ this.response = response; ++ } ++ ++ /** ++ * Get query type ++ * ++ * @return query type ++ */ ++ @NotNull ++ public QueryType getQueryType() { ++ return this.queryType; ++ } ++ ++ /** ++ * Get querier address ++ * ++ * @return querier address ++ */ ++ @NotNull ++ public InetAddress getQuerierAddress() { ++ return this.querierAddress; ++ } ++ ++ /** ++ * Get query response ++ * ++ * @return query response ++ */ ++ @NotNull ++ public QueryResponse getResponse() { ++ return this.response; ++ } ++ ++ /** ++ * Set query response ++ * ++ * @param response query response ++ */ ++ public void setResponse(@NotNull QueryResponse response) { ++ this.response = Preconditions.checkNotNull(response, "response"); ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++ ++ /** ++ * The type of query ++ */ ++ public enum QueryType { ++ /** ++ * Basic query asks only a subset of information, such as motd, game type (hardcoded to <pre>MINECRAFT</pre>), map, ++ * current players, max players, server port and server motd ++ */ ++ BASIC, ++ ++ /** ++ * Full query asks pretty much everything present on this event (only hardcoded values cannot be modified here). ++ */ ++ FULL ++ } ++ ++ public final static class QueryResponse { ++ ++ private final String motd; ++ private final String gameVersion; ++ private final String map; ++ private final int currentPlayers; ++ private final int maxPlayers; ++ private final String hostname; ++ private final int port; ++ private final Collection<String> players; ++ private final String serverVersion; ++ private final Collection<PluginInformation> plugins; ++ ++ private QueryResponse(String motd, String gameVersion, String map, int currentPlayers, int maxPlayers, String hostname, int port, Collection<String> players, String serverVersion, Collection<PluginInformation> plugins) { ++ this.motd = motd; ++ this.gameVersion = gameVersion; ++ this.map = map; ++ this.currentPlayers = currentPlayers; ++ this.maxPlayers = maxPlayers; ++ this.hostname = hostname; ++ this.port = port; ++ this.players = players; ++ this.serverVersion = serverVersion; ++ this.plugins = plugins; ++ } ++ ++ /** ++ * Get motd which will be used to reply to the query. By default it is {@link Server#getMotd()}. ++ * ++ * @return motd ++ */ ++ @NotNull ++ public String getMotd() { ++ return this.motd; ++ } ++ ++ /** ++ * Get game version which will be used to reply to the query. By default supported Minecraft versions range is sent. ++ * ++ * @return game version ++ */ ++ @NotNull ++ public String getGameVersion() { ++ return this.gameVersion; ++ } ++ ++ /** ++ * Get map name which will be used to reply to the query. By default {@code world} is sent. ++ * ++ * @return map name ++ */ ++ @NotNull ++ public String getMap() { ++ return this.map; ++ } ++ ++ /** ++ * Get current online player count which will be used to reply to the query. ++ * ++ * @return online player count ++ */ ++ public int getCurrentPlayers() { ++ return this.currentPlayers; ++ } ++ ++ /** ++ * Get max player count which will be used to reply to the query. ++ * ++ * @return max player count ++ */ ++ public int getMaxPlayers() { ++ return this.maxPlayers; ++ } ++ ++ /** ++ * Get server (public facing) hostname. ++ * ++ * @return server hostname ++ */ ++ @NotNull ++ public String getHostname() { ++ return this.hostname; ++ } ++ ++ /** ++ * Get server (public facing) port. ++ * ++ * @return server port ++ */ ++ public int getPort() { ++ return this.port; ++ } ++ ++ /** ++ * Get collection of players which will be used to reply to the query. ++ * ++ * @return collection of players ++ */ ++ @NotNull ++ public Collection<String> getPlayers() { ++ return this.players; ++ } ++ ++ /** ++ * Get server software (name and version) which will be used to reply to the query. ++ * ++ * @return server software ++ */ ++ @NotNull ++ public String getServerVersion() { ++ return this.serverVersion; ++ } ++ ++ /** ++ * Get list of plugins which will be used to reply to the query. ++ * ++ * @return collection of plugins ++ */ ++ @NotNull ++ public Collection<PluginInformation> getPlugins() { ++ return this.plugins; ++ } ++ ++ /** ++ * Creates a new {@link Builder} instance from data represented by this response. ++ * ++ * @return {@link QueryResponse} builder ++ */ ++ @NotNull ++ public Builder toBuilder() { ++ return QueryResponse.builder() ++ .motd(getMotd()) ++ .gameVersion(getGameVersion()) ++ .map(getMap()) ++ .currentPlayers(getCurrentPlayers()) ++ .maxPlayers(getMaxPlayers()) ++ .hostname(getHostname()) ++ .port(getPort()) ++ .players(getPlayers()) ++ .serverVersion(getServerVersion()) ++ .plugins(getPlugins()); ++ } ++ ++ /** ++ * Creates a new {@link Builder} instance. ++ * ++ * @return {@link QueryResponse} builder ++ */ ++ @NotNull ++ public static Builder builder() { ++ return new Builder(); ++ } ++ ++ /** ++ * A builder for {@link QueryResponse} objects. ++ */ ++ public static final class Builder { ++ private String motd; ++ private String gameVersion; ++ private String map; ++ private String hostname; ++ private String serverVersion; ++ ++ private int currentPlayers; ++ private int maxPlayers; ++ private int port; ++ ++ private final List<String> players = new ArrayList<>(); ++ private final List<PluginInformation> plugins = new ArrayList<>(); ++ ++ private Builder() {} ++ ++ @NotNull ++ public Builder motd(@NotNull String motd) { ++ this.motd = Preconditions.checkNotNull(motd, "motd"); ++ return this; ++ } ++ ++ @NotNull ++ public Builder gameVersion(@NotNull String gameVersion) { ++ this.gameVersion = Preconditions.checkNotNull(gameVersion, "gameVersion"); ++ return this; ++ } ++ ++ @NotNull ++ public Builder map(@NotNull String map) { ++ this.map = Preconditions.checkNotNull(map, "map"); ++ return this; ++ } ++ ++ @NotNull ++ public Builder currentPlayers(int currentPlayers) { ++ Preconditions.checkArgument(currentPlayers >= 0, "currentPlayers cannot be negative"); ++ this.currentPlayers = currentPlayers; ++ return this; ++ } ++ ++ @NotNull ++ public Builder maxPlayers(int maxPlayers) { ++ Preconditions.checkArgument(maxPlayers >= 0, "maxPlayers cannot be negative"); ++ this.maxPlayers = maxPlayers; ++ return this; ++ } ++ ++ @NotNull ++ public Builder hostname(@NotNull String hostname) { ++ this.hostname = Preconditions.checkNotNull(hostname, "hostname"); ++ return this; ++ } ++ ++ @NotNull ++ public Builder port(int port) { ++ Preconditions.checkArgument(port >= 1 && port <= 65535, "port must be between 1-65535"); ++ this.port = port; ++ return this; ++ } ++ ++ @NotNull ++ public Builder players(@NotNull Collection<String> players) { ++ this.players.addAll(Preconditions.checkNotNull(players, "players")); ++ return this; ++ } ++ ++ @NotNull ++ public Builder players(@NotNull String... players) { ++ this.players.addAll(Arrays.asList(Preconditions.checkNotNull(players, "players"))); ++ return this; ++ } ++ ++ @NotNull ++ public Builder clearPlayers() { ++ this.players.clear(); ++ return this; ++ } ++ ++ @NotNull ++ public Builder serverVersion(@NotNull String serverVersion) { ++ this.serverVersion = Preconditions.checkNotNull(serverVersion, "serverVersion"); ++ return this; ++ } ++ ++ @NotNull ++ public Builder plugins(@NotNull Collection<PluginInformation> plugins) { ++ this.plugins.addAll(Preconditions.checkNotNull(plugins, "plugins")); ++ return this; ++ } ++ ++ @NotNull ++ public Builder plugins(@NotNull PluginInformation... plugins) { ++ this.plugins.addAll(Arrays.asList(Preconditions.checkNotNull(plugins, "plugins"))); ++ return this; ++ } ++ ++ @NotNull ++ public Builder clearPlugins() { ++ this.plugins.clear(); ++ return this; ++ } ++ ++ /** ++ * Builds new {@link QueryResponse} with supplied data. ++ * ++ * @return response ++ */ ++ @NotNull ++ public QueryResponse build() { ++ return new QueryResponse( ++ Preconditions.checkNotNull(motd, "motd"), ++ Preconditions.checkNotNull(gameVersion, "gameVersion"), ++ Preconditions.checkNotNull(map, "map"), ++ currentPlayers, ++ maxPlayers, ++ Preconditions.checkNotNull(hostname, "hostname"), ++ port, ++ ImmutableList.copyOf(players), ++ Preconditions.checkNotNull(serverVersion, "serverVersion"), ++ ImmutableList.copyOf(plugins) ++ ); ++ } ++ } ++ ++ /** ++ * Plugin information ++ */ ++ public static class PluginInformation { ++ ++ private String name; ++ private String version; ++ ++ public PluginInformation(@NotNull String name, @NotNull String version) { ++ this.name = Preconditions.checkNotNull(name, "name"); ++ this.version = Preconditions.checkNotNull(version, "version"); ++ } ++ ++ @NotNull ++ public String getName() { ++ return this.name; ++ } ++ ++ public void setName(@NotNull String name) { ++ this.name = name; ++ } ++ ++ public void setVersion(@NotNull String version) { ++ this.version = version; ++ } ++ ++ @NotNull ++ public String getVersion() { ++ return this.version; ++ } ++ ++ @NotNull ++ public static PluginInformation of(@NotNull String name, @NotNull String version) { ++ return new PluginInformation(name, version); ++ } ++ } ++ } ++} |