13
0
geforkt von Mirrors/Paper
Dieser Commit ist enthalten in:
Nassim Jahnke 2021-06-13 11:41:07 +02:00
Ursprung bda639725b
Commit 43227a418f
19 geänderte Dateien mit 399 neuen und 800 gelöschten Zeilen

Datei anzeigen

@ -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")

Datei anzeigen

@ -14,9 +14,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/org/bukkit/entity/Entity.java
+++ b/src/main/java/org/bukkit/entity/Entity.java
@@ -0,0 +0,0 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent
*/
@NotNull
Chunk getChunk();
// TODO remove impl here
return getLocation().getChunk();
}
+
+ /**
+ * @return The {@link org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason} that spawned this entity.

Datei anzeigen

@ -1,271 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Fri, 15 Feb 2019 01:08:19 -0500
Subject: [PATCH] Allow Saving of Oversized Chunks
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.
This limit can be reached fairly easily with books, resulting in the chunk being unable
to save to the world. Worse off, is that nothing printed when this occured, and silently
performed a chunk rollback on next load.
This leads to security risk with duplication and is being actively exploited.
This patch catches the too large scenario, falls back and moves any large Entity
or Tile Entity into a new compound, and this compound is saved into a different file.
On Chunk Load, we check for oversized status, and if so, we load the extra file and
merge the Entities and Tile Entities from the oversized chunk back into the level to
then be loaded as normal.
Once a chunk is returned back to normal size, the oversized flag will clear, and no
extra data file will exist.
This fix maintains compatability with all existing Anvil Region Format tools as it
does not alter the save format. They will just not know about the extra entities.
This fix also maintains compatability if someone switches server jars to one without
this fix, as the data will remain in the oversized file. Once the server returns
to a jar with this fix, the data will be restored.
diff --git a/src/main/java/net/minecraft/nbt/NbtIo.java b/src/main/java/net/minecraft/nbt/NbtIo.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/nbt/NbtIo.java
+++ b/src/main/java/net/minecraft/nbt/NbtIo.java
@@ -0,0 +0,0 @@ public class NbtIo {
}
+ public static CompoundTag readNBT(DataInput datainput) throws IOException { return read(datainput); } // Paper - OBFHELPER
public static CompoundTag read(DataInput input) throws IOException {
return read(input, NbtAccounter.UNLIMITED);
}
@@ -0,0 +0,0 @@ public class NbtIo {
}
}
+ public static void writeNBT(CompoundTag nbttagcompound, DataOutput dataoutput) throws IOException { write(nbttagcompound, dataoutput); } // Paper - OBFHELPER
public static void write(CompoundTag tag, DataOutput output) throws IOException {
writeUnnamedTag((Tag) tag, output);
}
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
@@ -0,0 +0,0 @@ import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.nio.file.StandardOpenOption;
+import java.util.zip.InflaterInputStream; // Paper
+
import javax.annotation.Nullable;
import net.minecraft.Util;
+import net.minecraft.nbt.CompoundTag;
+import net.minecraft.nbt.NbtIo;
import net.minecraft.world.level.ChunkPos;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable {
private final IntBuffer timestamps;
@VisibleForTesting
protected final RegionBitmap usedSectors;
+ public final File file; // Paper
public RegionFile(File file, File directory, boolean dsync) throws IOException {
this(file.toPath(), directory.toPath(), RegionFileVersion.VERSION_DEFLATE, dsync);
@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable {
public RegionFile(Path file, Path directory, RegionFileVersion outputChunkStreamVersion, boolean dsync) throws IOException {
this.header = ByteBuffer.allocateDirect(8192);
+ this.file = file.toFile(); // Paper
+ initOversizedState(); // Paper
this.usedSectors = new RegionBitmap();
this.version = outputChunkStreamVersion;
if (!Files.isDirectory(directory, new LinkOption[0])) {
@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable {
void run() throws IOException;
}
+ // Paper start
+ private final byte[] oversized = new byte[1024];
+ private int oversizedCount = 0;
+
+ private synchronized void initOversizedState() throws IOException {
+ File metaFile = getOversizedMetaFile();
+ if (metaFile.exists()) {
+ final byte[] read = java.nio.file.Files.readAllBytes(metaFile.toPath());
+ System.arraycopy(read, 0, oversized, 0, oversized.length);
+ for (byte temp : oversized) {
+ oversizedCount += temp;
+ }
+ }
+ }
+
+ private static int getChunkIndex(int x, int z) {
+ return (x & 31) + (z & 31) * 32;
+ }
+ synchronized boolean isOversized(int x, int z) {
+ return this.oversized[getChunkIndex(x, z)] == 1;
+ }
+ synchronized void setOversized(int x, int z, boolean oversized) throws IOException {
+ final int offset = getChunkIndex(x, z);
+ boolean previous = this.oversized[offset] == 1;
+ this.oversized[offset] = (byte) (oversized ? 1 : 0);
+ if (!previous && oversized) {
+ oversizedCount++;
+ } else if (!oversized && previous) {
+ oversizedCount--;
+ }
+ if (previous && !oversized) {
+ File oversizedFile = getOversizedFile(x, z);
+ if (oversizedFile.exists()) {
+ oversizedFile.delete();
+ }
+ }
+ if (oversizedCount > 0) {
+ if (previous != oversized) {
+ writeOversizedMeta();
+ }
+ } else if (previous) {
+ File oversizedMetaFile = getOversizedMetaFile();
+ if (oversizedMetaFile.exists()) {
+ oversizedMetaFile.delete();
+ }
+ }
+ }
+
+ private void writeOversizedMeta() throws IOException {
+ java.nio.file.Files.write(getOversizedMetaFile().toPath(), oversized);
+ }
+
+ private File getOversizedMetaFile() {
+ return new File(this.file.getParentFile(), this.file.getName().replaceAll("\\.mca$", "") + ".oversized.nbt");
+ }
+
+ private File getOversizedFile(int x, int z) {
+ return new File(this.file.getParentFile(), this.file.getName().replaceAll("\\.mca$", "") + "_oversized_" + x + "_" + z + ".nbt");
+ }
+
+ synchronized CompoundTag getOversizedData(int x, int z) throws IOException {
+ File file = getOversizedFile(x, z);
+ try (DataInputStream out = new DataInputStream(new BufferedInputStream(new InflaterInputStream(new java.io.FileInputStream(file))))) {
+ return NbtIo.readNBT((java.io.DataInput) out);
+ }
+
+ }
+ // Paper end
class ChunkBuffer extends ByteArrayOutputStream {
private final ChunkPos pos;
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
@@ -0,0 +0,0 @@ import java.io.File;
import java.io.IOException;
import javax.annotation.Nullable;
import net.minecraft.nbt.CompoundTag;
+import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.NbtIo;
+import net.minecraft.nbt.Tag;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.ExceptionCollector;
import net.minecraft.world.level.ChunkPos;
@@ -0,0 +0,0 @@ public final class RegionFileStorage implements AutoCloseable {
}
}
+ // Paper start
+ private static void printOversizedLog(String msg, File file, int x, int z) {
+ org.apache.logging.log4j.LogManager.getLogger().fatal(msg + " (" + file.toString().replaceAll(".+[\\\\/]", "") + " - " + x + "," + z + ") Go clean it up to remove this message. /minecraft:tp " + (x<<4)+" 128 "+(z<<4) + " - DO NOT REPORT THIS TO PAPER - You may ask for help on Discord, but do not file an issue. These error messages can not be removed.");
+ }
+
+ private static final int DEFAULT_SIZE_THRESHOLD = 1024 * 8;
+ private static final int OVERZEALOUS_TOTAL_THRESHOLD = 1024 * 64;
+ private static final int OVERZEALOUS_THRESHOLD = 1024;
+ private static int SIZE_THRESHOLD = DEFAULT_SIZE_THRESHOLD;
+ private static void resetFilterThresholds() {
+ SIZE_THRESHOLD = Math.max(1024 * 4, Integer.getInteger("Paper.FilterThreshhold", DEFAULT_SIZE_THRESHOLD));
+ }
+ static {
+ resetFilterThresholds();
+ }
+
+ static boolean isOverzealous() {
+ return SIZE_THRESHOLD == OVERZEALOUS_THRESHOLD;
+ }
+
+
+ private static CompoundTag readOversizedChunk(RegionFile regionfile, ChunkPos chunkCoordinate) throws IOException {
+ synchronized (regionfile) {
+ try (DataInputStream datainputstream = regionfile.getReadStream(chunkCoordinate)) {
+ CompoundTag oversizedData = regionfile.getOversizedData(chunkCoordinate.x, chunkCoordinate.z);
+ CompoundTag chunk = NbtIo.readNBT((DataInput) datainputstream);
+ if (oversizedData == null) {
+ return chunk;
+ }
+ CompoundTag oversizedLevel = oversizedData.getCompound("Level");
+ CompoundTag level = chunk.getCompound("Level");
+
+ mergeChunkList(level, oversizedLevel, "Entities");
+ mergeChunkList(level, oversizedLevel, "TileEntities");
+
+ chunk.put("Level", level);
+
+ return chunk;
+ } catch (Throwable throwable) {
+ throwable.printStackTrace();
+ throw throwable;
+ }
+ }
+ }
+
+ private static void mergeChunkList(CompoundTag level, CompoundTag oversizedLevel, String key) {
+ ListTag levelList = level.getList(key, 10);
+ ListTag oversizedList = oversizedLevel.getList(key, 10);
+
+ if (!oversizedList.isEmpty()) {
+ levelList.addAll(oversizedList);
+ level.put(key, levelList);
+ }
+ }
+
+ private static int getNBTSize(Tag nbtBase) {
+ DataOutputStream test = new DataOutputStream(new org.apache.commons.io.output.NullOutputStream());
+ try {
+ nbtBase.write(test);
+ return test.size();
+ } catch (IOException e) {
+ e.printStackTrace();
+ return 0;
+ }
+ }
+
+ // Paper End
+
@Nullable
public CompoundTag read(ChunkPos pos) throws IOException {
// CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing
@@ -0,0 +0,0 @@ public final class RegionFileStorage implements AutoCloseable {
}
// CraftBukkit end
DataInputStream datainputstream = regionfile.getChunkDataInputStream(pos);
+ // Paper start
+ if (regionfile.isOversized(pos.x, pos.z)) {
+ printOversizedLog("Loading Oversized Chunk!", regionfile.file, pos.x, pos.z);
+ return readOversizedChunk(regionfile, pos);
+ }
+ // Paper end
Throwable throwable = null;
CompoundTag nbttagcompound;
@@ -0,0 +0,0 @@ public final class RegionFileStorage implements AutoCloseable {
try {
NbtIo.write(tag, (DataOutput) dataoutputstream);
+ regionfile.setOversized(pos.x, pos.z, false); // Paper - We don't do this anymore, mojang stores differently, but clear old meta flag if it exists to get rid of our own meta file once last oversized is gone
} catch (Throwable throwable1) {
throwable = throwable1;
throw throwable1;

Datei anzeigen

@ -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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/rcon/NetworkDataOutputStream.java
+++ b/src/main/java/net/minecraft/server/rcon/NetworkDataOutputStream.java
@@ -0,0 +0,0 @@ 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java
+++ b/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java
@@ -0,0 +0,0 @@ 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;
@@ -0,0 +0,0 @@ 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");
@@ -0,0 +0,0 @@ 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);
}
@@ -0,0 +0,0 @@ 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();
}
}

Datei anzeigen

@ -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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/level/ServerEntity.java
+++ b/src/main/java/net/minecraft/server/level/ServerEntity.java
@@ -0,0 +0,0 @@ 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -0,0 +0,0 @@ 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()) {

Datei anzeigen

@ -18,9 +18,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
@ -47,30 +47,30 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.vehicle.Boat;
@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s
@@ -0,0 +0,0 @@ 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
@@ -0,0 +0,0 @@ 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()));
@@ -0,0 +0,0 @@ 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);
@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s
nbt.putBoolean("Paper.FromMobSpawner", true);
@@ -0,0 +0,0 @@ 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 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ 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;
+ }
+ }
@ -97,13 +97,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java
+++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java
@@ -0,0 +0,0 @@ public abstract class BaseSpawner {
// Spigot End
}
// 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java

Datei anzeigen

@ -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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/rcon/NetworkDataOutputStream.java
+++ b/src/main/java/net/minecraft/server/rcon/NetworkDataOutputStream.java
@@ -0,0 +0,0 @@ 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java
+++ b/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java
@@ -0,0 +0,0 @@ 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);
@@ -0,0 +0,0 @@ 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();
}
}

Datei anzeigen

@ -13,42 +13,38 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java
@@ -0,0 +0,0 @@ public class ClientboundLevelChunkPacket implements Packet<ClientGamePacketListe
private boolean fullChunk;
public ClientboundLevelChunkPacket() {}
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, int includedSectionsMask) {
ChunkPos chunkcoordintpair = chunk.getPos();
public ClientboundLevelChunkPacket(LevelChunk chunk) {
ChunkPos chunkPos = chunk.getPos();
@@ -0,0 +0,0 @@ public class ClientboundLevelChunkPacket implements Packet<ClientGamePacketListe
this.availableSections = this.extractChunkData(new FriendlyByteBuf(this.getWriteBuffer()), chunk, includedSectionsMask);
this.buffer = new byte[this.calculateChunkSize(chunk)];
this.availableSections = this.extractChunkData(new FriendlyByteBuf(this.getWriteBuffer()), chunk);
this.blockEntitiesTags = Lists.newArrayList();
iterator = chunk.getBlockEntities().entrySet().iterator();
+ int totalTileEntities = 0; // Paper
while (iterator.hasNext()) {
entry = (Entry) iterator.next();
@@ -0,0 +0,0 @@ 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;
+ }
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 nbttagcompound = tileentity.getUpdateTag();
if (tileentity instanceof SkullBlockEntity) { SkullBlockEntity.sanitizeTileEntityUUID(nbttagcompound); } // Paper
+ }
+ // 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);

Datei anzeigen

@ -9,7 +9,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -0,0 +0,0 @@ public abstract class PlayerList {
// this.a(entityplayer1, entityplayer, worldserver1); // CraftBukkit - removed
boolean flag2 = false;
+ // Paper start

Datei anzeigen

@ -27,19 +27,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
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) {
@@ -0,0 +0,0 @@ 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

Datei anzeigen

@ -31,22 +31,6 @@ diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/network/Connection.java
+++ b/src/main/java/net/minecraft/network/Connection.java
@@ -0,0 +0,0 @@ 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;
@@ -0,0 +0,0 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
public int protocolVersion;
public java.net.InetSocketAddress virtualHost;
@ -71,7 +55,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
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 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // 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 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+ 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 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } 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
private void sendPacket(Packet<?> packet, @Nullable GenericFutureListener<? extends Future<? super Void>> callback) {
@@ -0,0 +0,0 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
this.channel.config().setAutoRead(false);
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 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // 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 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper end
public void tick() {
- this.flushQueue();
+ this.p();
if (this.packetListener instanceof ServerLoginPacketListenerImpl) {
((ServerLoginPacketListenerImpl) this.packetListener).tick();
}
this.flushQueue();
@@ -0,0 +0,0 @@ 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;
@ -314,13 +260,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
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) {
@@ -0,0 +0,0 @@ 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
@ -331,64 +277,23 @@ diff --git a/src/main/java/net/minecraft/network/protocol/Packet.java b/src/main
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/network/protocol/Packet.java
+++ b/src/main/java/net/minecraft/network/protocol/Packet.java
@@ -0,0 +0,0 @@
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;
@@ -0,0 +0,0 @@ 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java
+++ b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java
@@ -0,0 +0,0 @@ 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;
@@ -0,0 +0,0 @@ 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
@@ -0,0 +0,0 @@ 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);

Datei anzeigen

@ -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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
@@ -0,0 +0,0 @@ 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) {
@@ -0,0 +0,0 @@ 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/level/ServerEntity.java
+++ b/src/main/java/net/minecraft/server/level/ServerEntity.java
@@ -0,0 +0,0 @@ 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -0,0 +0,0 @@ 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -0,0 +0,0 @@ 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;

Datei anzeigen

@ -15,17 +15,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
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
@@ -0,0 +0,0 @@ public class ClientboundChatPacket implements Packet<ClientGamePacketListener> {
//packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(components)); // Paper - comment, replaced with below
// 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

Datei anzeigen

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