Mirror von
https://github.com/PaperMC/Paper.git
synchronisiert 2024-12-15 11:00:06 +01:00
c97ce029e9
PaperMC believes that 1.16.2 is now ready for general release as we fixed the main issue plagueing the 1.16.x release, the MapLike data conversion issues. Until now, it was not safe for a server to convert a world to 1.16.2 without data conversion issues around villages and potentially other things. If you did, those MapLike errors meant something went wrong. This is now resolved. Big thanks to all those that helped, notably @BillyGalbreath and @Proximyst who did large parts of the update process with me. Please as always, backup your worlds and test before updating to 1.16.2! If you update to 1.16.2, there is no going back to an older build than this. --------------------------------- Co-authored-by: William Blake Galbreath <Blake.Galbreath@GMail.com> Co-authored-by: Mariell Hoversholm <proximyst@proximyst.com> Co-authored-by: krolik-exe <69214078+krolik-exe@users.noreply.github.com> Co-authored-by: BillyGalbreath <BillyGalbreath@users.noreply.github.com> Co-authored-by: stonar96 <minecraft.stonar96@gmail.com> Co-authored-by: Shane Freeder <theboyetronic@gmail.com> Co-authored-by: Jason <jasonpenilla2@me.com> Co-authored-by: kashike <kashike@vq.lc> Co-authored-by: Aurora <21148213+aurorasmiles@users.noreply.github.com> Co-authored-by: KennyTV <kennytv@t-online.de> Co-authored-by: commandblockguy <commandblockguy1@gmail.com> Co-authored-by: DigitalRegent <misterwener@gmail.com> Co-authored-by: ishland <ishlandmc@yeah.net>
425 Zeilen
13 KiB
Diff
425 Zeilen
13 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Mark Vainomaa <mikroskeem@mikroskeem.eu>
|
|
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..77a19995f6792a182c5a43d6714e7bda0f42df5b
|
|
--- /dev/null
|
|
+++ b/src/main/java/com/destroystokyo/paper/event/server/GS4QueryEvent.java
|
|
@@ -0,0 +1,412 @@
|
|
+package com.destroystokyo.paper.event.server;
|
|
+
|
|
+import com.google.common.base.Preconditions;
|
|
+import com.google.common.collect.ImmutableList;
|
|
+import org.bukkit.event.Event;
|
|
+import org.bukkit.event.HandlerList;
|
|
+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
|
|
+ *
|
|
+ * Adapted from Velocity's ProxyQueryEvent
|
|
+ *
|
|
+ * @author Mark Vainomaa
|
|
+ */
|
|
+public final class GS4QueryEvent extends Event {
|
|
+ private static final HandlerList handlers = new HandlerList();
|
|
+
|
|
+ private final QueryType queryType;
|
|
+ private final InetAddress querierAddress;
|
|
+ private QueryResponse response;
|
|
+
|
|
+ public GS4QueryEvent(@NotNull QueryType queryType, @NotNull InetAddress querierAddress, @NotNull QueryResponse response) {
|
|
+ super(true); // should always be called async
|
|
+ this.queryType = Preconditions.checkNotNull(queryType, "queryType");
|
|
+ this.querierAddress = Preconditions.checkNotNull(querierAddress, "querierAddress");
|
|
+ this.response = Preconditions.checkNotNull(response, "response");
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Get query type
|
|
+ * @return query type
|
|
+ */
|
|
+ @NotNull
|
|
+ public QueryType getQueryType() {
|
|
+ return queryType;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Get querier address
|
|
+ * @return querier address
|
|
+ */
|
|
+ @NotNull
|
|
+ public InetAddress getQuerierAddress() {
|
|
+ return querierAddress;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Get query response
|
|
+ * @return query response
|
|
+ */
|
|
+ @NotNull
|
|
+ public QueryResponse getResponse() {
|
|
+ return response;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Set query response
|
|
+ * @param response query response
|
|
+ */
|
|
+ public void setResponse(@NotNull QueryResponse response) {
|
|
+ this.response = Preconditions.checkNotNull(response, "response");
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public String toString() {
|
|
+ return "GS4QueryEvent{" +
|
|
+ "queryType=" + queryType +
|
|
+ ", querierAddress=" + querierAddress +
|
|
+ ", response=" + response +
|
|
+ '}';
|
|
+ }
|
|
+
|
|
+ @NotNull
|
|
+ @Override
|
|
+ public HandlerList getHandlers() {
|
|
+ return handlers;
|
|
+ }
|
|
+
|
|
+ @NotNull
|
|
+ public static HandlerList getHandlerList() {
|
|
+ return handlers;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * 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 org.bukkit.Server#getMotd()}.
|
|
+ * @return motd
|
|
+ */
|
|
+ @NotNull
|
|
+ public String getMotd() {
|
|
+ return 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 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 map;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Get current online player count which will be used to reply to the query.
|
|
+ * @return online player count
|
|
+ */
|
|
+ public int getCurrentPlayers() {
|
|
+ return currentPlayers;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Get max player count which will be used to reply to the query.
|
|
+ * @return max player count
|
|
+ */
|
|
+ public int getMaxPlayers() {
|
|
+ return maxPlayers;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Get server (public facing) hostname
|
|
+ * @return server hostname
|
|
+ */
|
|
+ @NotNull
|
|
+ public String getHostname() {
|
|
+ return hostname;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Get server (public facing) port
|
|
+ * @return server port
|
|
+ */
|
|
+ public int getPort() {
|
|
+ return port;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Get collection of players which will be used to reply to the query.
|
|
+ * @return collection of players
|
|
+ */
|
|
+ @NotNull
|
|
+ public Collection<String> getPlayers() {
|
|
+ return players;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Get server software (name and version) which will be used to reply to the query.
|
|
+ * @return server software
|
|
+ */
|
|
+ @NotNull
|
|
+ public String getServerVersion() {
|
|
+ return serverVersion;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Get list of plugins which will be used to reply to the query.
|
|
+ * @return collection of plugins
|
|
+ */
|
|
+ @NotNull
|
|
+ public Collection<PluginInformation> getPlugins() {
|
|
+ return 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 List<String> players = new ArrayList<>();
|
|
+ private 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 name;
|
|
+ }
|
|
+
|
|
+ public void setName(@NotNull String name) {
|
|
+ this.name = name;
|
|
+ }
|
|
+
|
|
+ public void setVersion(@NotNull String version) {
|
|
+ this.version = version;
|
|
+ }
|
|
+
|
|
+ @NotNull
|
|
+ public String getVersion() {
|
|
+ return version;
|
|
+ }
|
|
+
|
|
+ @NotNull
|
|
+ public static PluginInformation of(@NotNull String name, @NotNull String version) {
|
|
+ return new PluginInformation(name, version);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+}
|