aboutsummaryrefslogtreecommitdiffhomepage
path: root/patches/api/0163-Add-GS4-Query-event.patch
diff options
context:
space:
mode:
Diffstat (limited to 'patches/api/0163-Add-GS4-Query-event.patch')
-rw-r--r--patches/api/0163-Add-GS4-Query-event.patch436
1 files changed, 436 insertions, 0 deletions
diff --git a/patches/api/0163-Add-GS4-Query-event.patch b/patches/api/0163-Add-GS4-Query-event.patch
new file mode 100644
index 0000000000..a153279317
--- /dev/null
+++ b/patches/api/0163-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);
++ }
++ }
++ }
++}