aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMark Vainomaa <[email protected]>2019-03-24 19:01:31 +0200
committerDaniel Ennis <[email protected]>2019-03-24 13:01:31 -0400
commit556259dd97e07f69bad7f4ce9e4d1d4079a8dd96 (patch)
treeca77f70c869cc50fabf0e9cdaa83cbf4e44ee5cc
parent0f82626d760eb359d117d1e430b11c12549a2f66 (diff)
downloadPaper-556259dd97e07f69bad7f4ce9e4d1d4079a8dd96.tar.gz
Paper-556259dd97e07f69bad7f4ce9e4d1d4079a8dd96.zip
Add GS4 query event (#1906)
-rw-r--r--Spigot-API-Patches/0176-Add-GS4-Query-event.patch426
-rw-r--r--Spigot-Server-Patches/0426-Fire-event-on-GS4-query.patch220
2 files changed, 646 insertions, 0 deletions
diff --git a/Spigot-API-Patches/0176-Add-GS4-Query-event.patch b/Spigot-API-Patches/0176-Add-GS4-Query-event.patch
new file mode 100644
index 0000000000..2a4d5975f0
--- /dev/null
+++ b/Spigot-API-Patches/0176-Add-GS4-Query-event.patch
@@ -0,0 +1,426 @@
+From 784e07fa6c5fa8c82d5da5f08f79563f467231ca 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 000000000..2ead0466e
+--- /dev/null
++++ b/src/main/java/com/destroystokyo/paper/event/server/GS4QueryEvent.java
+@@ -0,0 +1,411 @@
++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) {
++ 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);
++ }
++ }
++ }
++}
+--
+2.21.0
+
diff --git a/Spigot-Server-Patches/0426-Fire-event-on-GS4-query.patch b/Spigot-Server-Patches/0426-Fire-event-on-GS4-query.patch
new file mode 100644
index 0000000000..f203d2b489
--- /dev/null
+++ b/Spigot-Server-Patches/0426-Fire-event-on-GS4-query.patch
@@ -0,0 +1,220 @@
+From 7ec017a7334afb1f9abf3e69d755fdc797ce68ed Mon Sep 17 00:00:00 2001
+From: Mark Vainomaa <[email protected]>
+Date: Sun, 17 Mar 2019 21:46:56 +0200
+Subject: [PATCH] Fire event on GS4 query
+
+
+diff --git a/src/main/java/net/minecraft/server/RemoteConnectionThread.java b/src/main/java/net/minecraft/server/RemoteConnectionThread.java
+index d875b799ac..bcc36bbbfa 100644
+--- a/src/main/java/net/minecraft/server/RemoteConnectionThread.java
++++ b/src/main/java/net/minecraft/server/RemoteConnectionThread.java
+@@ -15,7 +15,7 @@ public abstract class RemoteConnectionThread implements Runnable {
+ private static final Logger h = LogManager.getLogger();
+ private static final AtomicInteger i = new AtomicInteger(0);
+ protected boolean a;
+- protected IMinecraftServer b;
++ protected IMinecraftServer b; protected IMinecraftServer getServer() { return b; } // Paper - OBFHELPER
+ protected final String c;
+ protected Thread d;
+ protected int e = 5;
+@@ -58,6 +58,7 @@ public abstract class RemoteConnectionThread implements Runnable {
+ this.b.f(s);
+ }
+
++ protected int getPlayerCount() { return d(); } // Paper - OBFHELPER
+ protected int d() {
+ return this.b.getPlayerCount();
+ }
+diff --git a/src/main/java/net/minecraft/server/RemoteStatusListener.java b/src/main/java/net/minecraft/server/RemoteStatusListener.java
+index 7dd81564a2..fd981931b0 100644
+--- a/src/main/java/net/minecraft/server/RemoteStatusListener.java
++++ b/src/main/java/net/minecraft/server/RemoteStatusListener.java
+@@ -21,19 +21,19 @@ public class RemoteStatusListener extends RemoteConnectionThread {
+
+ private long h;
+ private int i;
+- private final int j;
+- private final int k;
+- private final String l;
+- private final String m;
++ private final int j; private int getServerPort() { return j; } // Paper - OBFHELPER
++ private final int k; private int getMaxPlayers() { return k; } // Paper - OBFHELPER
++ private final String l; private String getMotd() { return l; } // Paper - OBFHELPER
++ private final String m; private String getWorldName() { return m; } // Paper - OBFHELPER
+ private DatagramSocket n;
+ private final byte[] o = new byte[1460];
+ private DatagramPacket p;
+ private final Map<SocketAddress, String> q;
+- private String r;
++ private String r; private String getServerHost() { return r; } // Paper - OBFHELPER
+ private String s;
+ private final Map<SocketAddress, RemoteStatusListener.RemoteStatusChallenge> t;
+ private final long u;
+- private final RemoteStatusReply v;
++ private final RemoteStatusReply v; private RemoteStatusReply getCachedFullResponse() { return v; } // Paper - OBFHELPER
+ private long w;
+
+ public RemoteStatusListener(IMinecraftServer iminecraftserver) {
+@@ -99,6 +99,7 @@ public class RemoteStatusListener extends RemoteConnectionThread {
+
+ remotestatusreply.a((int) 0);
+ remotestatusreply.a(this.a(datagrampacket.getSocketAddress()));
++ /* Paper start - GS4 Query event
+ remotestatusreply.a(this.l);
+ remotestatusreply.a("SMP");
+ remotestatusreply.a(this.m);
+@@ -106,6 +107,31 @@ public class RemoteStatusListener extends RemoteConnectionThread {
+ remotestatusreply.a(Integer.toString(this.k));
+ remotestatusreply.a((short) this.j);
+ remotestatusreply.a(this.r);
++ */
++ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryType queryType =
++ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryType.BASIC;
++ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse queryResponse = com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.builder()
++ .motd(this.getMotd())
++ .map(this.getWorldName())
++ .currentPlayers(this.getPlayerCount())
++ .maxPlayers(this.getMaxPlayers())
++ .port(this.getServerPort())
++ .hostname(this.getServerHost())
++ .gameVersion(this.getServer().getVersion())
++ .serverVersion(org.bukkit.Bukkit.getServer().getName() + " on " + org.bukkit.Bukkit.getServer().getBukkitVersion())
++ .build();
++ com.destroystokyo.paper.event.server.GS4QueryEvent queryEvent =
++ new com.destroystokyo.paper.event.server.GS4QueryEvent(queryType, datagrampacket.getAddress(), queryResponse);
++ queryEvent.callEvent();
++ queryResponse = queryEvent.getResponse();
++ remotestatusreply.writeString(queryResponse.getMotd());
++ remotestatusreply.writeString("SMP");
++ remotestatusreply.writeString(queryResponse.getMap());
++ remotestatusreply.writeString(Integer.toString(queryResponse.getCurrentPlayers()));
++ remotestatusreply.writeString(Integer.toString(queryResponse.getMaxPlayers()));
++ remotestatusreply.writeShort((short) queryResponse.getPort());
++ remotestatusreply.writeString(queryResponse.getHostname());
++ // Paper end
+ this.a(remotestatusreply.a(), datagrampacket);
+ this.a("Status [" + socketaddress + "]");
+ }
+@@ -142,6 +168,7 @@ public class RemoteStatusListener extends RemoteConnectionThread {
+ this.v.a("splitnum");
+ this.v.a((int) 128);
+ this.v.a((int) 0);
++ /* Paper start - GS4 Query event
+ this.v.a("hostname");
+ this.v.a(this.l);
+ this.v.a("gametype");
+@@ -177,6 +204,79 @@ public class RemoteStatusListener extends RemoteConnectionThread {
+ }
+
+ this.v.a((int) 0);
++ */
++ // Pack plugins
++ java.util.List<com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.PluginInformation> plugins = java.util.Collections.emptyList();
++ org.bukkit.plugin.Plugin[] bukkitPlugins;
++ if(((DedicatedServer) this.getServer()).server.getQueryPlugins() && (bukkitPlugins = org.bukkit.Bukkit.getPluginManager().getPlugins()).length > 0) {
++ plugins = java.util.stream.Stream.of(bukkitPlugins)
++ .map(plugin -> com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.PluginInformation.of(plugin.getName(), plugin.getDescription().getVersion()))
++ .collect(java.util.stream.Collectors.toList());
++ }
++
++ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse queryResponse = com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.builder()
++ .motd(this.getMotd())
++ .map(this.getWorldName())
++ .currentPlayers(this.getPlayerCount())
++ .maxPlayers(this.getMaxPlayers())
++ .port(this.getServerPort())
++ .hostname(this.getServerHost())
++ .plugins(plugins)
++ .players(this.getServer().getPlayers())
++ .gameVersion(this.getServer().getVersion())
++ .serverVersion(org.bukkit.Bukkit.getServer().getName() + " on " + org.bukkit.Bukkit.getServer().getBukkitVersion())
++ .build();
++ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryType queryType =
++ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryType.FULL;
++ com.destroystokyo.paper.event.server.GS4QueryEvent queryEvent =
++ new com.destroystokyo.paper.event.server.GS4QueryEvent(queryType, datagrampacket.getAddress(), queryResponse);
++ queryEvent.callEvent();
++ queryResponse = queryEvent.getResponse();
++ this.getCachedFullResponse().writeString("hostname");
++ this.getCachedFullResponse().writeString(queryResponse.getMotd());
++ this.getCachedFullResponse().writeString("gametype");
++ this.getCachedFullResponse().writeString("SMP");
++ this.getCachedFullResponse().writeString("game_id");
++ this.getCachedFullResponse().writeString("MINECRAFT");
++ this.getCachedFullResponse().writeString("version");
++ this.getCachedFullResponse().writeString(queryResponse.getGameVersion());
++ this.getCachedFullResponse().writeString("plugins");
++ java.lang.StringBuilder pluginsString = new java.lang.StringBuilder();
++ pluginsString.append(queryResponse.getServerVersion());
++ if(!queryResponse.getPlugins().isEmpty()) {
++ pluginsString.append(": ");
++ Iterator<com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.PluginInformation> iter = queryResponse.getPlugins().iterator();
++ while(iter.hasNext()) {
++ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.PluginInformation info = iter.next();
++ pluginsString.append(info.getName());
++ if (info.getVersion() != null) {
++ pluginsString.append(' ').append(info.getVersion().replaceAll(";", ","));
++ }
++ if (iter.hasNext()) {
++ pluginsString.append(';').append(' ');
++ }
++ }
++ }
++ this.getCachedFullResponse().writeString(pluginsString.toString());
++ this.getCachedFullResponse().writeString("map");
++ this.getCachedFullResponse().writeString(queryResponse.getMap());
++ this.getCachedFullResponse().writeString("numplayers");
++ this.getCachedFullResponse().writeString(Integer.toString(queryResponse.getCurrentPlayers()));
++ this.getCachedFullResponse().writeString("maxplayers");
++ this.getCachedFullResponse().writeString(Integer.toString(queryResponse.getMaxPlayers()));
++ this.getCachedFullResponse().writeString("hostport");
++ this.getCachedFullResponse().writeString(Integer.toString(queryResponse.getPort()));
++ this.getCachedFullResponse().writeString("hostip");
++ this.getCachedFullResponse().writeString(queryResponse.getHostname());
++ // The "meaningless data" start, copied from above
++ this.getCachedFullResponse().writeInt(0);
++ this.getCachedFullResponse().writeInt(1);
++ this.getCachedFullResponse().writeString("player_");
++ this.getCachedFullResponse().writeInt(0);
++ // "Meaningless data" end
++ queryResponse.getPlayers().forEach(this.getCachedFullResponse()::writeStringUnchecked);
++ this.getCachedFullResponse().writeInt(0);
++ // Paper end
+ return this.v.a();
+ }
+ }
+diff --git a/src/main/java/net/minecraft/server/RemoteStatusReply.java b/src/main/java/net/minecraft/server/RemoteStatusReply.java
+index 848b5c3f0e..9e8c8b3df2 100644
+--- a/src/main/java/net/minecraft/server/RemoteStatusReply.java
++++ b/src/main/java/net/minecraft/server/RemoteStatusReply.java
+@@ -18,15 +18,27 @@ public class RemoteStatusReply {
+ this.b.write(abyte, 0, abyte.length);
+ }
+
++ public void writeString(String string) throws IOException { a(string); } // Paper - OBFHELPER
+ public void a(String s) throws IOException {
+ this.b.writeBytes(s);
+ this.b.write(0);
+ }
++ // Paper start - unchecked exception variant to use in Stream API
++ public void writeStringUnchecked(String string) {
++ try {
++ writeString(string);
++ } catch (IOException e) {
++ com.destroystokyo.paper.util.SneakyThrow.sneaky(e);
++ }
++ }
++ // Paper end
+
++ public void writeInt(int i) throws IOException { a(i); } // Paper - OBFHELPER
+ public void a(int i) throws IOException {
+ this.b.write(i);
+ }
+
++ public void writeShort(short i) throws IOException { a(i); } // Paper - OBFHELPER
+ public void a(short short0) throws IOException {
+ this.b.writeShort(Short.reverseBytes(short0));
+ }
+--
+2.21.0
+