This commit is contained in:
KennyTV 2021-06-13 11:41:07 +02:00
parent 76a75fc35a
commit d42140148f
No known key found for this signature in database
GPG Key ID: 6BE3B555EBC5982B
20 changed files with 466 additions and 594 deletions

View File

@ -1,7 +1,7 @@
plugins {
java
id("com.github.johnrengelman.shadow") version "7.0.0" apply false
id("io.papermc.paperweight.core") version "1.0.0-SNAPSHOT"
id("io.papermc.paperweight.core") version "1.0.0-LOCAL-SNAPSHOT"
}
val mcVersion = providers.gradleProperty("mcVersion")

View File

@ -10,13 +10,13 @@ persistenting Living Entity, SPAWNER for spawners,
or DEFAULT since data was not stored.
diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java
index 4b1f9b0ad5dc9ad6f33fddafc376b6f983a556ef..5b382091b1466b25ad42325d5808785a8e948552 100644
index 92927b9a90b2a4497dd572f6f752c40cf35dd8b8..4a6d58ef68b782291b4d26a8515be326481f5209 100644
--- a/src/main/java/org/bukkit/entity/Entity.java
+++ b/src/main/java/org/bukkit/entity/Entity.java
@@ -708,5 +708,11 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent
*/
@NotNull
Chunk getChunk();
@@ -711,5 +711,11 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent
// TODO remove impl here
return getLocation().getChunk();
}
+
+ /**
+ * @return The {@link org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason} that spawned this entity.

View File

@ -3,6 +3,8 @@ From: Aikar <aikar@aikar.co>
Date: Fri, 15 Feb 2019 01:08:19 -0500
Subject: [PATCH] Allow Saving of Oversized Chunks
Note 1.17 update: With 1.17, Entities are no longer stored in chunk slices, so this needs updating!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
The Minecraft World Region File format has a hard cap of 1MB per chunk.
This is due to the fact that the header of the file format only allocates
a single byte for sector count, meaning a maximum of 256 sectors, at 4k per sector.

View File

@ -1,54 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Wed, 6 May 2020 05:00:57 -0400
Subject: [PATCH] Handle Oversized Tile Entities in chunks
Splits out Extra Packets if too many TE's are encountered to prevent
creating too large of a packet to sed.
Co authored by Spottedleaf
diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java
index b7d303b5f51a35504888933efef74564fa01e59d..b587f774c8f88f2a1c3ea489f7e4fe0bbdeb5a41 100644
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java
@@ -34,7 +34,15 @@ public class ClientboundLevelChunkPacket implements Packet<ClientGamePacketListe
private boolean fullChunk;
public ClientboundLevelChunkPacket() {}
+ // Paper start
+ private final java.util.List<Packet> extraPackets = new java.util.ArrayList<>();
+ private static final int TE_LIMIT = Integer.getInteger("Paper.excessiveTELimit", 750);
+ @Override
+ public java.util.List<Packet> getExtraPackets() {
+ return extraPackets;
+ }
+ // Paper end
public ClientboundLevelChunkPacket(LevelChunk chunk, int includedSectionsMask) {
ChunkPos chunkcoordintpair = chunk.getPos();
@@ -61,6 +69,7 @@ public class ClientboundLevelChunkPacket implements Packet<ClientGamePacketListe
this.availableSections = this.extractChunkData(new FriendlyByteBuf(this.getWriteBuffer()), chunk, includedSectionsMask);
this.blockEntitiesTags = Lists.newArrayList();
iterator = chunk.getBlockEntities().entrySet().iterator();
+ int totalTileEntities = 0; // Paper
while (iterator.hasNext()) {
entry = (Entry) iterator.next();
@@ -69,6 +78,15 @@ public class ClientboundLevelChunkPacket implements Packet<ClientGamePacketListe
int j = blockposition.getY() >> 4;
if (this.isFullChunk() || (includedSectionsMask & 1 << j) != 0) {
+ // Paper start - improve oversized chunk data packet handling
+ if (++totalTileEntities > TE_LIMIT) {
+ ClientboundBlockEntityDataPacket updatePacket = tileentity.getUpdatePacket();
+ if (updatePacket != null) {
+ this.extraPackets.add(updatePacket);
+ continue;
+ }
+ }
+ // Paper end
CompoundTag nbttagcompound = tileentity.getUpdateTag();
if (tileentity instanceof SkullBlockEntity) { SkullBlockEntity.sanitizeTileEntityUUID(nbttagcompound); } // Paper

View File

@ -1,43 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: AgentTroll <woodyc40@gmail.com>
Date: Fri, 22 Mar 2019 22:24:03 -0700
Subject: [PATCH] Update entity Metadata for all tracked players
diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java
index 49c71b21b6b88bc41ca6ddf4c76186ce522ee456..1609ab94c86e964421f996d4d46aef30f8b8e696 100644
--- a/src/main/java/net/minecraft/server/level/ServerEntity.java
+++ b/src/main/java/net/minecraft/server/level/ServerEntity.java
@@ -420,6 +420,12 @@ public class ServerEntity {
return ClientboundMoveEntityPacket.packetToEntity(this.xp, this.yp, this.zp);
}
+ // Paper start - Add broadcast method
+ void broadcast(Packet<?> packet) {
+ this.getPacketConsumer().accept(packet);
+ }
+ // Paper end
+
private void broadcastAndSend(Packet<?> packet) {
this.broadcast.accept(packet);
if (this.entity instanceof ServerPlayer) {
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index d6d8d83bc16572474d56a278dd119eacc2c52476..ed4129a51351aff16455960d71a0add1b8209c02 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -2286,7 +2286,14 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener {
if (event.isCancelled() || this.player.inventory.getSelected() == null || this.player.inventory.getSelected().getItem() != origItem) {
// Refresh the current entity metadata
- this.send(new ClientboundSetEntityDataPacket(entity.getId(), entity.getEntityData(), true));
+ // Paper start - update entity for all players
+ ClientboundSetEntityDataPacket packet1 = new ClientboundSetEntityDataPacket(entity.getId(), entity.getEntityData(), true);
+ if (entity.tracker != null) {
+ entity.tracker.broadcast(packet1);
+ } else {
+ this.send(packet1);
+ }
+ // Paper end
}
if (event.isCancelled()) {

View File

@ -1,265 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mark Vainomaa <mikroskeem@mikroskeem.eu>
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/rcon/NetworkDataOutputStream.java b/src/main/java/net/minecraft/server/rcon/NetworkDataOutputStream.java
index d10de580430d754204b36de809376538a14591e6..f6f0539a8e6edbeb1c412cee753a282b24a38046 100644
--- a/src/main/java/net/minecraft/server/rcon/NetworkDataOutputStream.java
+++ b/src/main/java/net/minecraft/server/rcon/NetworkDataOutputStream.java
@@ -18,15 +18,27 @@ public class NetworkDataOutputStream {
this.dataOutputStream.write(abyte, 0, abyte.length);
}
+ public void writeString(String string) throws IOException { this.writeString(string); } // Paper - OBFHELPER
public void writeString(String s) throws IOException {
this.dataOutputStream.writeBytes(s);
this.dataOutputStream.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 { this.write(i); } // Paper - OBFHELPER
public void write(int i) throws IOException {
this.dataOutputStream.write(i);
}
+ public void writeShort(short i) throws IOException { this.writeShort(i); } // Paper - OBFHELPER
public void writeShort(short short0) throws IOException {
this.dataOutputStream.writeShort(Short.reverseBytes(short0));
}
diff --git a/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java b/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java
index 170d047463154bd6851199f06fe343ccb1896213..5562a3caff328bb08857b4f06a79b1e52f390fdd 100644
--- a/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java
+++ b/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java
@@ -16,6 +16,7 @@ import java.util.Random;
import javax.annotation.Nullable;
import net.minecraft.Util;
import net.minecraft.server.ServerInterface;
+import net.minecraft.server.dedicated.DedicatedServer;
import net.minecraft.server.rcon.NetworkDataOutputStream;
import net.minecraft.server.rcon.PktUtils;
import org.apache.logging.log4j.LogManager;
@@ -26,18 +27,18 @@ public class QueryThreadGs4 extends GenericThread {
private static final Logger LOGGER = LogManager.getLogger();
private long lastChallengeCheck;
private final int port;
- private final int serverPort;
- private final int maxPlayers;
- private final String serverName;
- private final String worldName;
+ private final int serverPort; private final int getServerPort() { return this.serverPort; } // Paper - OBFHELPER
+ private final int maxPlayers; private final int getMaxPlayers() { return this.maxPlayers; } // Paper - OBFHELPER
+ private final String serverName; private final String getMotd() { return this.serverName; } // Paper - OBFHELPER
+ private final String worldName; private final String getWorldName() { return this.worldName; } // Paper - OBFHELPER
private DatagramSocket socket;
private final byte[] buffer = new byte[1460];
- private String hostIp;
+ private String hostIp; public final String getServerHost() { return this.hostIp; } // Paper - OBFHELPER
private String serverIp;
private final Map<SocketAddress, QueryThreadGs4.RequestChallenge> validChallenges;
- private final NetworkDataOutputStream rulesResponse;
+ private final NetworkDataOutputStream rulesResponse; private final NetworkDataOutputStream getCachedFullResponse() { return this.rulesResponse; } // Paper - OBFHELPER
private long lastRulesResponse;
- private final ServerInterface serverInterface;
+ private final ServerInterface serverInterface; private final ServerInterface getServer() { return this.serverInterface; } // Paper - OBFHELPER
private QueryThreadGs4(ServerInterface server, int queryPort) {
super("Query Listener");
@@ -107,13 +108,39 @@ public class QueryThreadGs4 extends GenericThread {
remotestatusreply.write((int) 0);
remotestatusreply.writeBytes(this.getIdentBytes(packet.getSocketAddress()));
- remotestatusreply.writeString(this.serverName);
+ /* Paper start - GS4 Query event
+ remotestatusreply.a(this.i);
+ remotestatusreply.a("SMP");
+ remotestatusreply.a(this.j);
+ remotestatusreply.a(Integer.toString(this.r.getPlayerCount()));
+ remotestatusreply.a(Integer.toString(this.h));
+ remotestatusreply.a((short) this.g);
+ remotestatusreply.a(this.m);
+ */
+ 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.getServer().getPlayerCount())
+ .maxPlayers(this.getMaxPlayers())
+ .port(this.getServerPort())
+ .hostname(this.getServerHost())
+ .gameVersion(this.getServer().getServerVersion())
+ .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, packet.getAddress(), queryResponse);
+ queryEvent.callEvent();
+ queryResponse = queryEvent.getResponse();
+ remotestatusreply.writeString(queryResponse.getMotd());
remotestatusreply.writeString("SMP");
- remotestatusreply.writeString(this.worldName);
- remotestatusreply.writeString(Integer.toString(this.serverInterface.getPlayerCount()));
- remotestatusreply.writeString(Integer.toString(this.maxPlayers));
- remotestatusreply.writeShort((short) this.serverPort);
- remotestatusreply.writeString(this.hostIp);
+ 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.sendTo(remotestatusreply.toByteArray(), packet);
QueryThreadGs4.LOGGER.debug("Status [{}]", socketaddress);
}
@@ -150,41 +177,115 @@ public class QueryThreadGs4 extends GenericThread {
this.rulesResponse.writeString("splitnum");
this.rulesResponse.write((int) 128);
this.rulesResponse.write((int) 0);
- this.rulesResponse.writeString("hostname");
- this.rulesResponse.writeString(this.serverName);
- this.rulesResponse.writeString("gametype");
- this.rulesResponse.writeString("SMP");
- this.rulesResponse.writeString("game_id");
- this.rulesResponse.writeString("MINECRAFT");
- this.rulesResponse.writeString("version");
- this.rulesResponse.writeString(this.serverInterface.getServerVersion());
- this.rulesResponse.writeString("plugins");
- this.rulesResponse.writeString(this.serverInterface.getPluginNames());
- this.rulesResponse.writeString("map");
- this.rulesResponse.writeString(this.worldName);
- this.rulesResponse.writeString("numplayers");
- this.rulesResponse.writeString("" + this.serverInterface.getPlayerCount());
- this.rulesResponse.writeString("maxplayers");
- this.rulesResponse.writeString("" + this.maxPlayers);
- this.rulesResponse.writeString("hostport");
- this.rulesResponse.writeString("" + this.serverPort);
- this.rulesResponse.writeString("hostip");
- this.rulesResponse.writeString(this.hostIp);
- this.rulesResponse.write((int) 0);
- this.rulesResponse.write((int) 1);
- this.rulesResponse.writeString("player_");
- this.rulesResponse.write((int) 0);
- String[] astring = this.serverInterface.getPlayerNames();
+ /* Paper start - GS4 Query event
+ this.p.a("hostname");
+ this.p.a(this.i);
+ this.p.a("gametype");
+ this.p.a("SMP");
+ this.p.a("game_id");
+ this.p.a("MINECRAFT");
+ this.p.a("version");
+ this.p.a(this.r.getVersion());
+ this.p.a("plugins");
+ this.p.a(this.r.getPlugins());
+ this.p.a("map");
+ this.p.a(this.j);
+ this.p.a("numplayers");
+ this.p.a("" + this.r.getPlayerCount());
+ this.p.a("maxplayers");
+ this.p.a("" + this.h);
+ this.p.a("hostport");
+ this.p.a("" + this.g);
+ this.p.a("hostip");
+ this.p.a(this.m);
+ this.p.a((int) 0);
+ this.p.a((int) 1);
+ this.p.a("player_");
+ this.p.a((int) 0);
+ String[] astring = this.r.getPlayers();
String[] astring1 = astring;
int j = astring.length;
for (int k = 0; k < j; ++k) {
String s = astring1[k];
- this.rulesResponse.writeString(s);
+ this.p.a(s);
}
- this.rulesResponse.write((int) 0);
+ this.p.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.getServer().getPlayerCount())
+ .maxPlayers(this.getMaxPlayers())
+ .port(this.getServerPort())
+ .hostname(this.getServerHost())
+ .plugins(plugins)
+ .players(this.getServer().getPlayerNames())
+ .gameVersion(this.getServer().getServerVersion())
+ .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, packet.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(": ");
+ java.util.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().replace(";", ","));
+ }
+ 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.rulesResponse.toByteArray();
}
}

View File

@ -28,26 +28,10 @@ and then catch exceptions and close if they fire.
Part of this commit was authored by: Spottedleaf
diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
index 3247ec5d6cf329ba0b7e6d5a6c3294dec2e34db4..fc63df21aecd4721efdb45d4744666ed0b562c1b 100644
index 9f0537799a3cae43fb120056b8fe805a4883cc4d..5897bdb4d1372fa3d7bdc482d02f0a54d8767bda 100644
--- a/src/main/java/net/minecraft/network/Connection.java
+++ b/src/main/java/net/minecraft/network/Connection.java
@@ -25,8 +25,15 @@ import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.PacketFlow;
+import net.minecraft.network.protocol.game.ClientboundBossEventPacket;
+import net.minecraft.network.protocol.game.ClientboundChatPacket;
+import net.minecraft.network.protocol.game.ClientboundCommandSuggestionsPacket;
import net.minecraft.network.protocol.game.ClientboundDisconnectPacket;
+import net.minecraft.network.protocol.game.ClientboundKeepAlivePacket;
+import net.minecraft.network.protocol.game.ClientboundSetTitlesPacket;
+import net.minecraft.server.MCUtil;
import net.minecraft.server.RunningOnDifferentThreadException;
+import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.network.ServerGamePacketListenerImpl;
import net.minecraft.server.network.ServerLoginPacketListenerImpl;
import net.minecraft.util.LazyLoadedValue;
@@ -75,6 +82,10 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
@@ -87,6 +87,10 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
public int protocolVersion;
public java.net.InetSocketAddress virtualHost;
private static boolean enableExplicitFlush = Boolean.getBoolean("paper.explicit-flush");
@ -58,7 +42,7 @@ index 3247ec5d6cf329ba0b7e6d5a6c3294dec2e34db4..fc63df21aecd4721efdb45d4744666ed
// Paper end
public Connection(PacketFlow side) {
@@ -98,6 +109,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
@@ -110,6 +114,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
}
public void setProtocol(ConnectionProtocol state) {
@ -66,12 +50,12 @@ index 3247ec5d6cf329ba0b7e6d5a6c3294dec2e34db4..fc63df21aecd4721efdb45d4744666ed
this.channel.attr(Connection.ATTRIBUTE_PROTOCOL).set(state);
this.channel.config().setAutoRead(true);
Connection.LOGGER.debug("Enabled auto read");
@@ -168,19 +180,84 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
@@ -186,19 +191,87 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
Validate.notNull(listener, "packetListener", new Object[0]);
this.packetListener = listener;
}
+ // Paper start
+ public ServerPlayer getPlayer() {
+ public net.minecraft.server.level.ServerPlayer getPlayer() {
+ if (packetListener instanceof ServerGamePacketListenerImpl) {
+ return ((ServerGamePacketListenerImpl) packetListener).player;
+ } else {
@ -101,11 +85,15 @@ index 3247ec5d6cf329ba0b7e6d5a6c3294dec2e34db4..fc63df21aecd4721efdb45d4744666ed
+ // Paper start
+ private static boolean canSendImmediate(Connection networkManager, Packet<?> packet) {
+ return networkManager.isPending || networkManager.protocol != ConnectionProtocol.PLAY ||
+ packet instanceof ClientboundKeepAlivePacket ||
+ packet instanceof ClientboundChatPacket ||
+ packet instanceof ClientboundCommandSuggestionsPacket ||
+ packet instanceof ClientboundSetTitlesPacket ||
+ packet instanceof ClientboundBossEventPacket;
+ packet instanceof net.minecraft.network.protocol.game.ClientboundKeepAlivePacket ||
+ packet instanceof net.minecraft.network.protocol.game.ClientboundChatPacket ||
+ packet instanceof net.minecraft.network.protocol.game.ClientboundCommandSuggestionsPacket ||
+ packet instanceof net.minecraft.network.protocol.game.ClientboundSetTitleTextPacket ||
+ packet instanceof net.minecraft.network.protocol.game.ClientboundSetSubtitleTextPacket ||
+ packet instanceof net.minecraft.network.protocol.game.ClientboundSetActionBarTextPacket ||
+ packet instanceof net.minecraft.network.protocol.game.ClientboundSetTitlesAnimationPacket ||
+ packet instanceof net.minecraft.network.protocol.game.ClientboundClearTitlesPacket ||
+ packet instanceof net.minecraft.network.protocol.game.ClientboundBossEventPacket;
+ }
+ // Paper end
+ }
@ -128,10 +116,10 @@ index 3247ec5d6cf329ba0b7e6d5a6c3294dec2e34db4..fc63df21aecd4721efdb45d4744666ed
+ }
+ packet.onPacketDispatch(getPlayer());
+ if (connected && (InnerUtil.canSendImmediate(this, packet) || (
+ MCUtil.isMainThread() && packet.isReady() && this.queue.isEmpty() &&
+ net.minecraft.server.MCUtil.isMainThread() && packet.isReady() && this.queue.isEmpty() &&
+ (packet.getExtraPackets() == null || packet.getExtraPackets().isEmpty())
+ ))) {
+ this.dispatchPacket(packet, callback);
+ this.send(packet, callback);
+ return;
}
+ // write the packets to the queue, then flush - antixray hooks there already
@ -142,106 +130,67 @@ index 3247ec5d6cf329ba0b7e6d5a6c3294dec2e34db4..fc63df21aecd4721efdb45d4744666ed
+ } else {
+ java.util.List<Connection.PacketHolder> packets = new java.util.ArrayList<>(1 + extraPackets.size());
+ packets.add(new Connection.PacketHolder(packet, null)); // delay the future listener until the end of the extra packets
+
+ for (int i = 0, len = extraPackets.size(); i < len;) {
+ Packet extra = extraPackets.get(i);
+ boolean end = ++i == len;
+ packets.add(new Connection.PacketHolder(extra, end ? callback : null)); // append listener to the end
+ }
+ this.queue.addAll(packets); // atomic
+ }
+ this.sendPacketQueue();
+ this.flushQueue();
+ // Paper end
}
private void dispatchPacket(Packet<?> packet, @Nullable GenericFutureListener<? extends Future<? super Void>> genericFutureListener) { this.sendPacket(packet, genericFutureListener); } // Paper - OBFHELPER
@@ -194,54 +271,119 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
this.channel.config().setAutoRead(false);
private void sendPacket(Packet<?> packet, @Nullable GenericFutureListener<? extends Future<? super Void>> callback) {
@@ -226,33 +299,79 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
this.setProtocol(enumprotocol);
}
+ ServerPlayer player = getPlayer(); // Paper
if (this.channel.eventLoop().inEventLoop()) {
if (enumprotocol != enumprotocol1) {
this.setProtocol(enumprotocol);
}
+ // Paper start
+ if (!isConnected()) {
+ packet.onPacketDispatchFinish(player, null);
+ return;
+ }
+ try {
+ // Paper end
ChannelFuture channelfuture = this.channel.writeAndFlush(packet);
if (callback != null) {
channelfuture.addListener(callback);
}
+ // Paper start
+ if (packet.hasFinishListener()) {
+ channelfuture.addListener((ChannelFutureListener) channelFuture -> packet.onPacketDispatchFinish(player, channelFuture));
+ }
+ // Paper end
channelfuture.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
+ // Paper start
+ } catch (Exception e) {
+ LOGGER.error("NetworkException: " + player, e);
+ disconnect(new TranslatableComponent("disconnect.genericReason", "Internal Exception: " + e.getMessage()));;
+ packet.onPacketDispatchFinish(player, null);
+ }
+ // Paper end
} else {
this.channel.eventLoop().execute(() -> {
if (enumprotocol != enumprotocol1) {
this.setProtocol(enumprotocol);
}
+ // Paper start
+ if (!isConnected()) {
+ packet.onPacketDispatchFinish(player, null);
+ return;
+ }
+ try {
+ // Paper end
ChannelFuture channelfuture1 = this.channel.writeAndFlush(packet);
+ // Paper start
+ net.minecraft.server.level.ServerPlayer player = getPlayer();
+ if (!isConnected()) {
+ packet.onPacketDispatchFinish(player, null);
+ return;
+ }
+
if (callback != null) {
channelfuture1.addListener(callback);
}
+ // Paper start
+ if (packet.hasFinishListener()) {
+ channelfuture1.addListener((ChannelFutureListener) channelFuture -> packet.onPacketDispatchFinish(player, channelFuture));
+ }
+ // Paper end
+ try {
+ // Paper end
ChannelFuture channelfuture = this.channel.writeAndFlush(packet);
channelfuture1.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
+ // Paper start
+ } catch (Exception e) {
+ LOGGER.error("NetworkException: " + player, e);
+ disconnect(new TranslatableComponent("disconnect.genericReason", "Internal Exception: " + e.getMessage()));;
+ packet.onPacketDispatchFinish(player, null);
+ }
+ // Paper end
});
if (genericfuturelistener != null) {
channelfuture.addListener(genericfuturelistener);
}
+ // Paper start
+ if (packet.hasFinishListener()) {
+ channelfuture.addListener((ChannelFutureListener) channelFuture -> packet.onPacketDispatchFinish(player, channelFuture));
+ }
+ // Paper end
channelfuture.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
+ // Paper start
+ } catch (Exception e) {
+ LOGGER.error("NetworkException: " + player, e);
+ disconnect(new net.minecraft.network.chat.TranslatableComponent("disconnect.genericReason", "Internal Exception: " + e.getMessage()));
+ packet.onPacketDispatchFinish(player, null);
+ }
+ // Paper end
}
private ConnectionProtocol getCurrentProtocol() {
return (ConnectionProtocol) this.channel.attr(Connection.ATTRIBUTE_PROTOCOL).get();
}
- private void sendPacketQueue() { this.flushQueue(); } // Paper - OBFHELPER
- private void flushQueue() {
- if (this.channel != null && this.channel.isOpen()) {
- Queue queue = this.queue;
-
+ // Paper start - rewrite this to be safer if ran off main thread
+ private boolean sendPacketQueue() { return this.p(); } // OBFHELPER // void -> boolean
+ private boolean p() { // void -> boolean
+ private boolean flushQueue() { // void -> boolean
+ if (!isConnected()) {
+ return true;
+ }
+ if (MCUtil.isMainThread()) {
+ if (net.minecraft.server.MCUtil.isMainThread()) {
+ return processQueue();
+ } else if (isPending) {
+ // Should only happen during login/status stages
@ -262,19 +211,19 @@ index 3247ec5d6cf329ba0b7e6d5a6c3294dec2e34db4..fc63df21aecd4721efdb45d4744666ed
+ // But if we are not on main due to login/status, the parent is synchronized on packetQueue
+ java.util.Iterator<PacketHolder> iterator = this.queue.iterator();
+ while (iterator.hasNext()) {
+ Connection.PacketHolder queued = iterator.next(); // poll -> peek
+ PacketHolder queued = iterator.next(); // poll -> peek
+
+ // Fix NPE (Spigot bug caused by handleDisconnection())
+ if (queued == null) {
+ return true;
+ }
+ Packet<?> packet = queued.getPacket();
+ Packet<?> packet = queued.packet;
+ if (!packet.isReady()) {
+ return false;
+ } else {
+ iterator.remove();
+ this.dispatchPacket(packet, queued.getGenericFutureListener());
+ this.sendPacket(packet, queued.listener);
}
}
+ return true;
@ -282,26 +231,23 @@ index 3247ec5d6cf329ba0b7e6d5a6c3294dec2e34db4..fc63df21aecd4721efdb45d4744666ed
+ // Paper end
public void tick() {
- this.flushQueue();
+ this.p();
if (this.packetListener instanceof ServerLoginPacketListenerImpl) {
((ServerLoginPacketListenerImpl) this.packetListener).tick();
}
@@ -271,9 +413,21 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
this.flushQueue();
@@ -289,9 +408,22 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
return this.address;
}
+ // Paper start
+ public void clearPacketQueue() {
+ ServerPlayer player = getPlayer();
+ net.minecraft.server.level.ServerPlayer player = getPlayer();
+ queue.forEach(queuedPacket -> {
+ Packet<?> packet = queuedPacket.getPacket();
+ Packet<?> packet = queuedPacket.packet;
+ if (packet.hasFinishListener()) {
+ packet.onPacketDispatchFinish(player, null);
+ }
+ });
+ queue.clear();
+ } // Paper end
+ }
+ // Paper end
public void disconnect(Component disconnectReason) {
// Spigot Start
this.preparing = false;
@ -309,18 +255,18 @@ index 3247ec5d6cf329ba0b7e6d5a6c3294dec2e34db4..fc63df21aecd4721efdb45d4744666ed
// Spigot End
if (this.channel.isOpen()) {
this.channel.close(); // We can't wait as this may be called from an event loop.
@@ -341,7 +495,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
@@ -409,7 +541,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
public void handleDisconnection() {
if (this.channel != null && !this.channel.isOpen()) {
if (this.disconnectionHandled) {
- Connection.LOGGER.warn("handleDisconnection() called twice");
+ //NetworkManager.LOGGER.warn("handleDisconnection() called twice"); // Paper - Do not log useless message
+ //Connection.LOGGER.warn("handleDisconnection() called twice"); // Paper - Do not log useless message
} else {
this.disconnectionHandled = true;
if (this.getDisconnectedReason() != null) {
@@ -349,7 +503,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
@@ -417,7 +549,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
} else if (this.getPacketListener() != null) {
this.getPacketListener().a(new TranslatableComponent("multiplayer.disconnect.generic"));
this.getPacketListener().onDisconnect(new TranslatableComponent("multiplayer.disconnect.generic"));
}
- this.queue.clear(); // Free up packet queue.
+ clearPacketQueue(); // Paper
@ -328,67 +274,26 @@ index 3247ec5d6cf329ba0b7e6d5a6c3294dec2e34db4..fc63df21aecd4721efdb45d4744666ed
final PacketListener packetListener = this.getPacketListener();
if (packetListener instanceof ServerGamePacketListenerImpl) {
diff --git a/src/main/java/net/minecraft/network/protocol/Packet.java b/src/main/java/net/minecraft/network/protocol/Packet.java
index 9914a82ba0ec146ab13fe94c4dbf0ebf64926536..22db5d0d2cc33498ca40162c66aa3b5fbf2f569f 100644
index 74bfe0d3942259c45702b099efdc4e101a4e3022..e8fcd56906d26f6dc87959e32c4c7c78cfea9658 100644
--- a/src/main/java/net/minecraft/network/protocol/Packet.java
+++ b/src/main/java/net/minecraft/network/protocol/Packet.java
@@ -1,5 +1,6 @@
package net.minecraft.network.protocol;
+import io.netty.channel.ChannelFuture; // Paper
import java.io.IOException;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.PacketListener;
@@ -13,6 +14,20 @@ public interface Packet<T extends PacketListener> {
@@ -9,6 +9,19 @@ public interface Packet<T extends PacketListener> {
void handle(T listener);
// Paper start
+
+ /**
+ * @param player Null if not at PLAY stage yet
+ */
+ default void onPacketDispatch(@javax.annotation.Nullable EntityPlayer player) {}
+ default void onPacketDispatch(@javax.annotation.Nullable net.minecraft.server.level.ServerPlayer player) {}
+
+ /**
+ * @param player Null if not at PLAY stage yet
+ * @param future Can be null if packet was cancelled
+ */
+ default void onPacketDispatchFinish(@javax.annotation.Nullable EntityPlayer player, @javax.annotation.Nullable ChannelFuture future) {}
+ default void onPacketDispatchFinish(@javax.annotation.Nullable net.minecraft.server.level.ServerPlayer player, @javax.annotation.Nullable io.netty.channel.ChannelFuture future) {}
+ default boolean hasFinishListener() { return false; }
+ default boolean isReady() { return true; }
+ default java.util.List<Packet> getExtraPackets() { return null; }
default boolean packetTooLarge(NetworkManager manager) {
default boolean packetTooLarge(net.minecraft.network.Connection manager) {
return false;
}
diff --git a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java
index 6cb51a4fe3c11f53fbb556ce6b0d64b735254d51..d46910cfdc0aef046a0c79731a85d381953c328a 100644
--- a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java
+++ b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java
@@ -16,6 +16,7 @@ import io.netty.channel.epoll.EpollServerSocketChannel;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.ServerSocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
+import io.netty.handler.flush.FlushConsolidationHandler; // Paper
import io.netty.handler.timeout.ReadTimeoutHandler;
import java.io.IOException;
import java.net.InetAddress;
@@ -54,10 +55,12 @@ public class ServerConnectionListener {
private final List<Connection> connections = Collections.synchronizedList(Lists.newArrayList());
// Paper start - prevent blocking on adding a new network manager while the server is ticking
private final java.util.Queue<Connection> pending = new java.util.concurrent.ConcurrentLinkedQueue<>();
+ private static final boolean disableFlushConsolidation = Boolean.getBoolean("Paper.disableFlushConsolidate"); // Paper
private void addPending() {
Connection manager = null;
while ((manager = pending.poll()) != null) {
connections.add(manager);
+ manager.isPending = false;
}
}
// Paper end
@@ -92,6 +95,7 @@ public class ServerConnectionListener {
;
}
+ if (!disableFlushConsolidation) channel.pipeline().addFirst(new FlushConsolidationHandler()); // Paper
channel.pipeline().addLast("timeout", new ReadTimeoutHandler(30)).addLast("legacy_query", new LegacyQueryHandler(ServerConnectionListener.this)).addLast("splitter", new Varint21FrameDecoder()).addLast("decoder", new PacketDecoder(PacketFlow.SERVERBOUND)).addLast("prepender", new Varint21LengthFieldPrepender()).addLast("encoder", new PacketEncoder(PacketFlow.CLIENTBOUND));
int j = ServerConnectionListener.this.server.getRateLimitPacketsPerSecond();
Object object = j > 0 ? new RateKickingConnection(j) : new Connection(PacketFlow.SERVERBOUND);

View File

@ -0,0 +1,50 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Wed, 6 May 2020 05:00:57 -0400
Subject: [PATCH] Handle Oversized Tile Entities in chunks
Splits out Extra Packets if too many TE's are encountered to prevent
creating too large of a packet to sed.
Co authored by Spottedleaf
diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java
index 96626835fee3c0fdb452acacdc9f737ad90c08de..c28879f32b004f36ff746ea2274f91ddd9501e71 100644
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java
@@ -27,6 +27,15 @@ public class ClientboundLevelChunkPacket implements Packet<ClientGamePacketListe
private final int[] biomes;
private final byte[] buffer;
private final List<CompoundTag> blockEntitiesTags;
+ // Paper start
+ private final java.util.List<Packet> extraPackets = new java.util.ArrayList<>();
+ private static final int TE_LIMIT = Integer.getInteger("Paper.excessiveTELimit", 750);
+
+ @Override
+ public java.util.List<Packet> getExtraPackets() {
+ return extraPackets;
+ }
+ // Paper end
public ClientboundLevelChunkPacket(LevelChunk chunk) {
ChunkPos chunkPos = chunk.getPos();
@@ -44,9 +53,19 @@ public class ClientboundLevelChunkPacket implements Packet<ClientGamePacketListe
this.buffer = new byte[this.calculateChunkSize(chunk)];
this.availableSections = this.extractChunkData(new FriendlyByteBuf(this.getWriteBuffer()), chunk);
this.blockEntitiesTags = Lists.newArrayList();
+ int totalTileEntities = 0; // Paper
for(Entry<BlockPos, BlockEntity> entry2 : chunk.getBlockEntities().entrySet()) {
BlockEntity blockEntity = entry2.getValue();
+ // Paper start - improve oversized chunk data packet handling
+ if (++totalTileEntities > TE_LIMIT) {
+ ClientboundBlockEntityDataPacket updatePacket = blockEntity.getUpdatePacket();
+ if (updatePacket != null) {
+ this.extraPackets.add(updatePacket);
+ continue;
+ }
+ }
+ // Paper end
CompoundTag compoundTag = blockEntity.getUpdateTag();
if (blockEntity instanceof net.minecraft.world.level.block.entity.SkullBlockEntity) { net.minecraft.world.level.block.entity.SkullBlockEntity.sanitizeTileEntityUUID(compoundTag); } // Paper
this.blockEntitiesTags.add(compoundTag);

View File

@ -11,10 +11,10 @@ everything to the Whitelist object.
https://github.com/PaperMC/Paper/issues/1880
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index 5b71b487836cdd2ddc75b2039f4dc0177719d345..8d133d3c825f7747081de99ee67d4556e5c19cdd 100644
index 0df68991eb2ef3dabe779f42c2bf44846ac0d862..4ae234a107d16bc71425af5f2729c428f79e3db7 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -55,6 +55,7 @@ import net.minecraft.network.protocol.game.ClientboundUpdateMobEffectPacket;
@@ -62,6 +62,7 @@ import net.minecraft.network.protocol.game.ClientboundUpdateMobEffectPacket;
import net.minecraft.network.protocol.game.ClientboundUpdateRecipesPacket;
import net.minecraft.network.protocol.game.ClientboundUpdateTagsPacket;
import net.minecraft.resources.ResourceKey;
@ -22,24 +22,15 @@ index 5b71b487836cdd2ddc75b2039f4dc0177719d345..8d133d3c825f7747081de99ee67d4556
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.PlayerAdvancements;
import net.minecraft.server.ServerScoreboard;
@@ -1012,9 +1013,9 @@ public abstract class PlayerList {
@@ -996,9 +997,9 @@ public abstract class PlayerList {
}
public boolean isWhitelisted(GameProfile gameprofile, org.bukkit.event.player.PlayerLoginEvent loginEvent) {
boolean isOp = this.ops.contains(gameprofile);
- boolean isWhitelisted = !this.doWhiteList || isOp || this.whitelist.contains(gameprofile);
+ boolean isWhitelisted = !this.isUsingWhitelist() || isOp || this.whitelist.contains(gameprofile);
+ boolean isWhitelisted = !this.isUsingWhitelist() || isOp || this.whitelist.contains(gameprofile); // Paper - use isUsingWhitelist()
final com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent event;
- event = new com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent(MCUtil.toBukkit(gameprofile), this.doWhiteList, isWhitelisted, isOp, org.spigotmc.SpigotConfig.whitelistMessage);
+ event = new com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent(MCUtil.toBukkit(gameprofile), this.isUsingWhitelist(), isWhitelisted, isOp, org.spigotmc.SpigotConfig.whitelistMessage);
- event = new com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent(net.minecraft.server.MCUtil.toBukkit(gameprofile), this.doWhiteList, isWhitelisted, isOp, org.spigotmc.SpigotConfig.whitelistMessage);
+ event = new com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent(net.minecraft.server.MCUtil.toBukkit(gameprofile), this.isUsingWhitelist(), isWhitelisted, isOp, org.spigotmc.SpigotConfig.whitelistMessage); // Paper - use isUsingWhitelist()
event.callEvent();
if (!event.isWhitelisted()) {
if (loginEvent != null) {
@@ -1062,7 +1063,7 @@ public abstract class PlayerList {
MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main
MinecraftTimings.savePlayers.startTiming(); // Paper
for (int i = 0; i < this.players.size(); ++i) {
- this.savePlayerFile((EntityPlayer) this.players.get(i));
+ this.save((ServerPlayer) this.players.get(i));
}
MinecraftTimings.savePlayers.stopTiming(); // Paper
return null; }); // Paper - ensure main

View File

@ -6,10 +6,10 @@ Subject: [PATCH] Set Zombie last tick at start of drowning process
Fixes GH-1887
diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java
index ad4eeb15771750193a28116117992270c72a3644..6fecf4188fc0247143edc688c03e645376960687 100644
index c60d9775230b2ff554eeb38136f8e7c32c47d8cf..ee17cba501e0cc4822bd1278d18b561c77fe9674 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java
@@ -220,6 +220,7 @@ public class Zombie extends Monster {
@@ -225,6 +225,7 @@ public class Zombie extends Monster {
++this.inWaterTime;
if (this.inWaterTime >= 600) {
this.startUnderWaterConversion(300);

View File

@ -5,10 +5,10 @@ Subject: [PATCH] Call WhitelistToggleEvent when whitelist is toggled
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index 8d133d3c825f7747081de99ee67d4556e5c19cdd..728eaadd3dc619e414ec30feb38c7d4a84b2e539 100644
index 4ae234a107d16bc71425af5f2729c428f79e3db7..ea336bdf2f15aabe74de82ef6c29b93573254e31 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -1131,6 +1131,7 @@ public abstract class PlayerList {
@@ -1115,6 +1115,7 @@ public abstract class PlayerList {
}
public void setUsingWhiteList(boolean whitelistEnabled) {

View File

@ -6,26 +6,26 @@ Subject: [PATCH] Use proper max length when serialising BungeeCord text
diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java
index f13da9e7d014bc00fbabf0a495b548bba2f59468..002a6c7933f64405707d7d34d3e5c17584539623 100644
index a64780b4b49d01322d8f755ff540a9622c89e983..26a229f7aa3f4425ed572e2d50730b4e978bf33e 100644
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java
@@ -9,7 +9,7 @@ import net.minecraft.network.chat.Component;
@@ -8,7 +8,7 @@ import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.Packet;
public class ClientboundChatPacket implements Packet<ClientGamePacketListener> {
-
+ private static final int MAX_LENGTH = Short.MAX_VALUE * 8 + 8; // Paper
private Component message;
private final Component message;
public net.kyori.adventure.text.Component adventure$message; // Paper
public net.md_5.bungee.api.chat.BaseComponent[] components; // Spigot
@@ -43,9 +43,9 @@ public class ClientboundChatPacket implements Packet<ClientGamePacketListener> {
//packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(components)); // Paper - comment, replaced with below
@@ -39,9 +39,9 @@ public class ClientboundChatPacket implements Packet<ClientGamePacketListener> {
// buf.writeUtf(net.md_5.bungee.chat.ComponentSerializer.toString(components)); // Paper - comment, replaced with below
// Paper start - don't nest if we don't need to so that we can preserve formatting
if (this.components.length == 1) {
- buf.writeByteArray(net.md_5.bungee.chat.ComponentSerializer.toString(this.components[0]));
- buf.writeUtf(net.md_5.bungee.chat.ComponentSerializer.toString(this.components[0]));
+ buf.writeUtf(net.md_5.bungee.chat.ComponentSerializer.toString(this.components[0]), MAX_LENGTH); // Paper - use proper max length
} else {
- buf.writeByteArray(net.md_5.bungee.chat.ComponentSerializer.toString(this.components));
- buf.writeUtf(net.md_5.bungee.chat.ComponentSerializer.toString(this.components));
+ buf.writeUtf(net.md_5.bungee.chat.ComponentSerializer.toString(this.components), MAX_LENGTH); // Paper - use proper max length
}
// Paper end

View File

@ -10,22 +10,22 @@ persistenting Living Entity, SPAWNER for spawners,
or DEFAULT since data was not stored.
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 2ab221e5315dde4e556ee49a6962ae0091ccf616..d03b4f97102dfb88927a94ee5a5d397ac493eaa1 100644
index 731c8e38c8daf04fee40a5ccfb0715b20f4d890f..940e6587125df1f203cdeeefc31658635badea81 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -1035,6 +1035,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
@@ -1093,6 +1093,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
// CraftBukkit start
private boolean addEntity0(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) {
org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot
+ if (entity.spawnReason == null) entity.spawnReason = spawnReason; // Paper
// Paper start
if (entity.valid) {
MinecraftServer.LOGGER.error("Attempted Double World add on " + entity, new Throwable());
if (entity.isRemoved()) {
// WorldServer.LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityTypes.getName(entity.getEntityType())); // CraftBukkit
return false;
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index 728eaadd3dc619e414ec30feb38c7d4a84b2e539..4d813b6556030354f51c1ee5f18eac2166b44576 100644
index ea336bdf2f15aabe74de82ef6c29b93573254e31..da3100d6577166e222164c174b28020541dd8e3a 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -331,7 +331,7 @@ public abstract class PlayerList {
@@ -335,7 +335,7 @@ public abstract class PlayerList {
// CraftBukkit start
ServerLevel finalWorldServer = worldserver1;
Entity entity = EntityType.loadEntityRecursive(nbttagcompound1.getCompound("Entity"), finalWorldServer, (entity1) -> {
@ -35,10 +35,10 @@ index 728eaadd3dc619e414ec30feb38c7d4a84b2e539..4d813b6556030354f51c1ee5f18eac21
});
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index d106118dbf4fb270f8526e40a767dd4c563a333f..6faac8773136412ca129dfa884178f311e197f6e 100644
index 8df9bd656374d0b43af378c61c1df7b951085b58..fcd3e6bfb4b1d0aefcb34eaec1212b08498dd5af 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -63,6 +63,8 @@ import net.minecraft.world.InteractionHand;
@@ -67,6 +67,8 @@ import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.Nameable;
import net.minecraft.world.damagesource.DamageSource;
@ -47,30 +47,30 @@ index d106118dbf4fb270f8526e40a767dd4c563a333f..6faac8773136412ca129dfa884178f31
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.vehicle.Boat;
@@ -157,6 +159,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s
@@ -166,6 +168,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n
}
}
};
public List<Entity> entitySlice = null;
+ public org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason;
// Paper end
public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper
@@ -1673,6 +1676,9 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s
tag.setUUID("Paper.OriginWorld", origin.getWorld().getUID());
tag.put("Paper.Origin", this.createList(origin.getX(), origin.getY(), origin.getZ()));
@@ -1841,6 +1844,9 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n
nbt.setUUID("Paper.OriginWorld", origin.getWorld().getUID());
nbt.put("Paper.Origin", this.newDoubleList(origin.getX(), origin.getY(), origin.getZ()));
}
+ if (spawnReason != null) {
+ tag.putString("Paper.SpawnReason", spawnReason.name());
+ nbt.putString("Paper.SpawnReason", spawnReason.name());
+ }
// Save entity's from mob spawner status
if (spawnedViaMobSpawner) {
tag.putBoolean("Paper.FromMobSpawner", true);
@@ -1811,6 +1817,26 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s
nbt.putBoolean("Paper.FromMobSpawner", true);
@@ -1983,6 +1989,26 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n
}
spawnedViaMobSpawner = tag.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status
+ if (tag.contains("Paper.SpawnReason")) {
+ String spawnReasonName = tag.getString("Paper.SpawnReason");
spawnedViaMobSpawner = nbt.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status
+ if (nbt.contains("Paper.SpawnReason")) {
+ String spawnReasonName = nbt.getString("Paper.SpawnReason");
+ try {
+ spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.valueOf(spawnReasonName);
+ } catch (Exception ignored) {
@ -81,7 +81,7 @@ index d106118dbf4fb270f8526e40a767dd4c563a333f..6faac8773136412ca129dfa884178f31
+ if (spawnedViaMobSpawner) {
+ spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER;
+ } else if (this instanceof Mob && (this instanceof Animal || this instanceof AbstractFish) && !((Mob) this).removeWhenFarAway(0.0)) {
+ if (!tag.getBoolean("PersistenceRequired")) {
+ if (!nbt.getBoolean("PersistenceRequired")) {
+ spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL;
+ }
+ }
@ -93,22 +93,22 @@ index d106118dbf4fb270f8526e40a767dd4c563a333f..6faac8773136412ca129dfa884178f31
} catch (Throwable throwable) {
diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java
index 1ce675d0d24ceb5724f5ac2d8f671e38f2735f74..3a7aec9bd2f3fd1b4a1981fb6a8c64b69e4875f8 100644
index 12a78685848b7fd945a472902d8200ea1d50b9ec..3aadcb472ab808ee981065ddfa86be6cbf38c8d9 100644
--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java
+++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java
@@ -183,6 +183,7 @@ public abstract class BaseSpawner {
// Spigot End
}
@@ -167,6 +167,7 @@ public abstract class BaseSpawner {
// Spigot End
}
entity.spawnedViaMobSpawner = true; // Paper
+ entity.spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER; // Paper
flag = true; // Paper
// Spigot Start
if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, blockposition).isCancelled()) {
+ entity.spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER; // Paper
flag = true; // Paper
// Spigot Start
if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, pos).isCancelled()) {
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
index e1bbaf620f3ed2a6cb9ce8007a78c4cee47b653e..7ad4fb57af32cc1b8278688381e1b058ed8437db 100644
index c381ea321b0fb3498e3f101ee059ac7d42aa029a..33bc56eba4229d844e3af6ff4662d96450e929af 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -1106,5 +1106,10 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
@@ -1163,5 +1163,10 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
public boolean fromMobSpawner() {
return getHandle().spawnedViaMobSpawner;
}

View File

@ -0,0 +1,76 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: AgentTroll <woodyc40@gmail.com>
Date: Fri, 22 Mar 2019 22:24:03 -0700
Subject: [PATCH] Update entity Metadata for all tracked players
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
index 8311d921ded1c81a1f561dc13db2010d2b7ce5d6..95ac30f56a9268f14d2518974c5a52e08f40ea18 100644
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
@@ -1281,6 +1281,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
} else {
ChunkMap.TrackedEntity playerchunkmap_entitytracker = new ChunkMap.TrackedEntity(entity, i, j, entitytypes.trackDeltas());
+ entity.tracker = playerchunkmap_entitytracker; // Paper - Fast access to tracker
this.entityMap.put(entity.getId(), playerchunkmap_entitytracker);
playerchunkmap_entitytracker.updatePlayers(this.level.players());
if (entity instanceof ServerPlayer) {
@@ -1323,7 +1324,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
if (playerchunkmap_entitytracker1 != null) {
playerchunkmap_entitytracker1.broadcastRemoved();
}
-
+ entity.tracker = null; // Paper - We're no longer tracked
}
protected void tick() {
diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java
index ad9bbda31a4cdb306ca40f2b99e4b815c4f136bd..28afe2f238ded241acf77c3272a44068646b9133 100644
--- a/src/main/java/net/minecraft/server/level/ServerEntity.java
+++ b/src/main/java/net/minecraft/server/level/ServerEntity.java
@@ -392,6 +392,12 @@ public class ServerEntity {
return ClientboundMoveEntityPacket.packetToEntity(this.xp, this.yp, this.zp);
}
+ // Paper start - Add broadcast method
+ void broadcast(Packet<?> packet) {
+ this.broadcast.accept(packet);
+ }
+ // Paper end
+
private void broadcastAndSend(Packet<?> packet) {
this.broadcast.accept(packet);
if (this.entity instanceof ServerPlayer) {
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index defebf7b45e4f006fa7e575b5dbd01ac1e231d5a..6c4266d847b1181a055fa425d5734032dadabf93 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -2289,7 +2289,14 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
if (event.isCancelled() || ServerGamePacketListenerImpl.this.player.getInventory().getSelected() == null || ServerGamePacketListenerImpl.this.player.getInventory().getSelected().getItem() != origItem) {
// Refresh the current entity metadata
- ServerGamePacketListenerImpl.this.send(new ClientboundSetEntityDataPacket(entity.getId(), entity.getEntityData(), true));
+ // Paper start - update entity for all players
+ ClientboundSetEntityDataPacket packet1 = new ClientboundSetEntityDataPacket(entity.getId(), entity.getEntityData(), true);
+ if (entity.tracker != null) {
+ entity.tracker.broadcast(packet1);
+ } else {
+ ServerGamePacketListenerImpl.this.send(packet1);
+ }
+ // Paper end
}
if (event.isCancelled()) {
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index fcd3e6bfb4b1d0aefcb34eaec1212b08498dd5af..a5159198003e43ce272ae73941d2be47d50eedc9 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -300,6 +300,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n
public boolean forceExplosionKnockback; // SPIGOT-949
public boolean persistentInvisibility = false;
public org.bukkit.Location origin; // Paper
+ public net.minecraft.server.level.ChunkMap.TrackedEntity tracker; // Paper - fast access to tracker
// Spigot start
public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this);
public final boolean defaultActivationState;

View File

@ -0,0 +1,209 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mark Vainomaa <mikroskeem@mikroskeem.eu>
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/rcon/NetworkDataOutputStream.java b/src/main/java/net/minecraft/server/rcon/NetworkDataOutputStream.java
index 51cb2644aa516a59e19fecb308d519dbc7e5fb11..e548aa0ca4e1e94ab628614b44fc11568ca3beff 100644
--- a/src/main/java/net/minecraft/server/rcon/NetworkDataOutputStream.java
+++ b/src/main/java/net/minecraft/server/rcon/NetworkDataOutputStream.java
@@ -22,6 +22,16 @@ public class NetworkDataOutputStream {
this.dataOutputStream.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 write(int value) throws IOException {
this.dataOutputStream.write(value);
}
diff --git a/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java b/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java
index 02bb0b2df37ead741adfef38d7479ba6f691dc2d..4632e8f0d27057bf3c47057124b347237ab58111 100644
--- a/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java
+++ b/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java
@@ -94,33 +94,52 @@ public class QueryThreadGs4 extends GenericThread {
if (3 <= i && -2 == bs[0] && -3 == bs[1]) {
LOGGER.debug("Packet '{}' [{}]", PktUtils.toHexString(bs[2]), socketAddress);
switch(bs[2]) {
- case 0:
- if (!this.validChallenge(packet)) {
- LOGGER.debug("Invalid challenge [{}]", (Object)socketAddress);
- return false;
- } else if (15 == i) {
- this.sendTo(this.buildRuleResponse(packet), packet);
- LOGGER.debug("Rules [{}]", (Object)socketAddress);
- } else {
- NetworkDataOutputStream networkDataOutputStream = new NetworkDataOutputStream(1460);
- networkDataOutputStream.write(0);
- networkDataOutputStream.writeBytes(this.getIdentBytes(packet.getSocketAddress()));
- networkDataOutputStream.writeString(this.serverName);
- networkDataOutputStream.writeString("SMP");
- networkDataOutputStream.writeString(this.worldName);
- networkDataOutputStream.writeString(Integer.toString(this.serverInterface.getPlayerCount()));
- networkDataOutputStream.writeString(Integer.toString(this.maxPlayers));
- networkDataOutputStream.writeShort((short)this.serverPort);
- networkDataOutputStream.writeString(this.hostIp);
- this.sendTo(networkDataOutputStream.toByteArray(), packet);
- LOGGER.debug("Status [{}]", (Object)socketAddress);
- }
- default:
- return true;
- case 9:
- this.sendChallenge(packet);
- LOGGER.debug("Challenge [{}]", (Object)socketAddress);
- return true;
+ case 0:
+ if (!this.validChallenge(packet)) {
+ LOGGER.debug("Invalid challenge [{}]", (Object)socketAddress);
+ return false;
+ } else if (15 == i) {
+ this.sendTo(this.buildRuleResponse(packet), packet);
+ LOGGER.debug("Rules [{}]", (Object)socketAddress);
+ } else {
+ NetworkDataOutputStream networkDataOutputStream = new NetworkDataOutputStream(1460);
+ networkDataOutputStream.write(0);
+ networkDataOutputStream.writeBytes(this.getIdentBytes(packet.getSocketAddress()));
+
+ 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.serverName)
+ .map(this.worldName)
+ .currentPlayers(this.serverInterface.getPlayerCount())
+ .maxPlayers(this.maxPlayers)
+ .port(this.serverPort)
+ .hostname(this.hostIp)
+ .gameVersion(this.serverInterface.getServerVersion())
+ .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, packet.getAddress(), queryResponse);
+ queryEvent.callEvent();
+ queryResponse = queryEvent.getResponse();
+
+ networkDataOutputStream.writeString(queryResponse.getMotd());
+ networkDataOutputStream.writeString("SMP");
+ networkDataOutputStream.writeString(queryResponse.getMap());
+ networkDataOutputStream.writeString(Integer.toString(queryResponse.getCurrentPlayers()));
+ networkDataOutputStream.writeString(Integer.toString(queryResponse.getMaxPlayers()));
+ networkDataOutputStream.writeShort((short) queryResponse.getPort());
+ networkDataOutputStream.writeString(queryResponse.getHostname());
+ // Paper end
+ this.sendTo(networkDataOutputStream.toByteArray(), packet);
+ LOGGER.debug("Status [{}]", (Object)socketAddress);
+ }
+ default:
+ return true;
+ case 9:
+ this.sendChallenge(packet);
+ LOGGER.debug("Challenge [{}]", (Object)socketAddress);
+ return true;
}
} else {
LOGGER.debug("Invalid packet [{}]", (Object)socketAddress);
@@ -146,37 +165,79 @@ public class QueryThreadGs4 extends GenericThread {
this.rulesResponse.writeString("splitnum");
this.rulesResponse.write(128);
this.rulesResponse.write(0);
+ // Paper start
+ // Pack plugins
+ java.util.List<com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.PluginInformation> plugins = java.util.Collections.emptyList();
+ org.bukkit.plugin.Plugin[] bukkitPlugins;
+ if (((net.minecraft.server.dedicated.DedicatedServer) this.serverInterface).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.serverName)
+ .map(this.worldName)
+ .currentPlayers(this.serverInterface.getPlayerCount())
+ .maxPlayers(this.maxPlayers)
+ .port(this.serverPort)
+ .hostname(this.hostIp)
+ .plugins(plugins)
+ .players(this.serverInterface.getPlayerNames())
+ .gameVersion(this.serverInterface.getServerVersion())
+ .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, packet.getAddress(), queryResponse);
+ queryEvent.callEvent();
+ queryResponse = queryEvent.getResponse();
this.rulesResponse.writeString("hostname");
- this.rulesResponse.writeString(this.serverName);
+ this.rulesResponse.writeString(queryResponse.getMotd());
this.rulesResponse.writeString("gametype");
this.rulesResponse.writeString("SMP");
this.rulesResponse.writeString("game_id");
this.rulesResponse.writeString("MINECRAFT");
this.rulesResponse.writeString("version");
- this.rulesResponse.writeString(this.serverInterface.getServerVersion());
+ this.rulesResponse.writeString(queryResponse.getGameVersion());
this.rulesResponse.writeString("plugins");
- this.rulesResponse.writeString(this.serverInterface.getPluginNames());
+ java.lang.StringBuilder pluginsString = new java.lang.StringBuilder();
+ pluginsString.append(queryResponse.getServerVersion());
+ if (!queryResponse.getPlugins().isEmpty()) {
+ pluginsString.append(": ");
+ java.util.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().replace(";", ","));
+ }
+ if (iter.hasNext()) {
+ pluginsString.append(';').append(' ');
+ }
+ }
+ }
+ this.rulesResponse.writeString(pluginsString.toString());
this.rulesResponse.writeString("map");
- this.rulesResponse.writeString(this.worldName);
+ this.rulesResponse.writeString(queryResponse.getMap());
this.rulesResponse.writeString("numplayers");
- this.rulesResponse.writeString("" + this.serverInterface.getPlayerCount());
+ this.rulesResponse.writeString(Integer.toString(queryResponse.getCurrentPlayers()));
this.rulesResponse.writeString("maxplayers");
- this.rulesResponse.writeString("" + this.maxPlayers);
+ this.rulesResponse.writeString(Integer.toString(queryResponse.getMaxPlayers()));
this.rulesResponse.writeString("hostport");
- this.rulesResponse.writeString("" + this.serverPort);
+ this.rulesResponse.writeString(Integer.toString(queryResponse.getPort()));
this.rulesResponse.writeString("hostip");
- this.rulesResponse.writeString(this.hostIp);
- this.rulesResponse.write(0);
- this.rulesResponse.write(1);
+ this.rulesResponse.writeString(queryResponse.getHostname());
+ // The "meaningless data" start, copied from above
+ this.rulesResponse.writeInt(0);
+ this.rulesResponse.writeInt(1);
this.rulesResponse.writeString("player_");
- this.rulesResponse.write(0);
- String[] strings = this.serverInterface.getPlayerNames();
-
- for(String string : strings) {
- this.rulesResponse.writeString(string);
- }
-
- this.rulesResponse.write(0);
+ this.rulesResponse.writeInt(0);
+ // "Meaningless data" end
+ queryResponse.getPlayers().forEach(this.rulesResponse::writeStringUnchecked);
+ this.rulesResponse.writeInt(0);
+ // Paper end
return this.rulesResponse.toByteArray();
}
}

View File

@ -5,11 +5,11 @@ Subject: [PATCH] Implement PlayerPostRespawnEvent
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index 4d813b6556030354f51c1ee5f18eac2166b44576..7412765020854caabd32fb6f4fffcf7f4bf6dba7 100644
index da3100d6577166e222164c174b28020541dd8e3a..c7956664427ca97544d1b47992a62c95d2fc9690 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -737,9 +737,14 @@ public abstract class PlayerList {
// this.a(entityplayer1, entityplayer, worldserver1); // CraftBukkit - removed
@@ -715,9 +715,14 @@ public abstract class PlayerList {
boolean flag2 = false;
+ // Paper start
@ -24,7 +24,7 @@ index 4d813b6556030354f51c1ee5f18eac2166b44576..7412765020854caabd32fb6f4fffcf7f
ServerLevel worldserver1 = this.server.getLevel(entityplayer.getRespawnDimension());
if (worldserver1 != null) {
Optional optional;
@@ -790,6 +795,7 @@ public abstract class PlayerList {
@@ -768,6 +773,7 @@ public abstract class PlayerList {
location = respawnEvent.getRespawnLocation();
if (!flag) entityplayer.reset(); // SPIGOT-4785
@ -32,7 +32,7 @@ index 4d813b6556030354f51c1ee5f18eac2166b44576..7412765020854caabd32fb6f4fffcf7f
} else {
location.setWorld(worldserver.getWorld());
}
@@ -847,6 +853,13 @@ public abstract class PlayerList {
@@ -825,6 +831,13 @@ public abstract class PlayerList {
if (entityplayer.connection.isDisconnected()) {
this.save(entityplayer);
}

View File

@ -1,5 +1,6 @@
pluginManagement {
repositories {
mavenLocal()
gradlePluginPortal()
maven("https://wav.jfrog.io/artifactory/repo/")
}