and here's some more patches
This commit is contained in:
parent
d9c1c30c58
commit
753267a57e
15 changed files with 83 additions and 69 deletions
|
@ -1,70 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Tue, 28 Jan 2014 19:13:57 -0500
|
||||
Subject: [PATCH] Add ItemStack Recipe API helper methods
|
||||
|
||||
Allows using ExactChoice Recipes with easier methodss
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/inventory/ShapedRecipe.java b/src/main/java/org/bukkit/inventory/ShapedRecipe.java
|
||||
index d742c4058ba9aed4fbe1591fd755a06608b06e98..222a12baa8e93ad686ab59426653f066d5876e38 100644
|
||||
--- a/src/main/java/org/bukkit/inventory/ShapedRecipe.java
|
||||
+++ b/src/main/java/org/bukkit/inventory/ShapedRecipe.java
|
||||
@@ -145,6 +145,13 @@ public class ShapedRecipe implements Recipe, Keyed {
|
||||
return this;
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @NotNull
|
||||
+ public ShapedRecipe setIngredient(char key, @NotNull ItemStack item) {
|
||||
+ return setIngredient(key, new RecipeChoice.ExactChoice(item));
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
/**
|
||||
* Get a copy of the ingredients map.
|
||||
*
|
||||
diff --git a/src/main/java/org/bukkit/inventory/ShapelessRecipe.java b/src/main/java/org/bukkit/inventory/ShapelessRecipe.java
|
||||
index 84062dd719cb8a6142dc8c806777cb208c6b42b2..7f6d3c71c5b3a9aa54c84a4c3b7c3614a0d477ce 100644
|
||||
--- a/src/main/java/org/bukkit/inventory/ShapelessRecipe.java
|
||||
+++ b/src/main/java/org/bukkit/inventory/ShapelessRecipe.java
|
||||
@@ -143,6 +143,40 @@ public class ShapelessRecipe implements Recipe, Keyed {
|
||||
return this;
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @NotNull
|
||||
+ public ShapelessRecipe addIngredient(@NotNull ItemStack item) {
|
||||
+ return addIngredient(item.getAmount(), item);
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public ShapelessRecipe addIngredient(int count, @NotNull ItemStack item) {
|
||||
+ Validate.isTrue(ingredients.size() + count <= 9, "Shapeless recipes cannot have more than 9 ingredients");
|
||||
+ while (count-- > 0) {
|
||||
+ ingredients.add(new RecipeChoice.ExactChoice(item));
|
||||
+ }
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public ShapelessRecipe removeIngredient(@NotNull ItemStack item) {
|
||||
+ return removeIngredient(1, item);
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public ShapelessRecipe removeIngredient(int count, @NotNull ItemStack item) {
|
||||
+ Iterator<RecipeChoice> iterator = ingredients.iterator();
|
||||
+ while (count > 0 && iterator.hasNext()) {
|
||||
+ ItemStack stack = iterator.next().getItemStack();
|
||||
+ if (stack.equals(item)) {
|
||||
+ iterator.remove();
|
||||
+ count--;
|
||||
+ }
|
||||
+ }
|
||||
+ return this;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
/**
|
||||
* Removes an ingredient from the list.
|
||||
*
|
|
@ -1,52 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Mark Vainomaa <mikroskeem@mikroskeem.eu>
|
||||
Date: Wed, 13 Mar 2019 20:04:43 +0200
|
||||
Subject: [PATCH] Add WhitelistToggleEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/event/server/WhitelistToggleEvent.java b/src/main/java/com/destroystokyo/paper/event/server/WhitelistToggleEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..fdd5eedb2b7401439912a3a4343a920f32edc860
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/event/server/WhitelistToggleEvent.java
|
||||
@@ -0,0 +1,40 @@
|
||||
+package com.destroystokyo.paper.event.server;
|
||||
+
|
||||
+import org.bukkit.event.Event;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+/**
|
||||
+ * This event is fired when whitelist is toggled
|
||||
+ *
|
||||
+ * @author Mark Vainomaa
|
||||
+ */
|
||||
+public class WhitelistToggleEvent extends Event {
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+
|
||||
+ private boolean enabled;
|
||||
+
|
||||
+ public WhitelistToggleEvent(boolean enabled) {
|
||||
+ this.enabled = enabled;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets whether whitelist is going to be enabled or not
|
||||
+ *
|
||||
+ * @return Whether whitelist is going to be enabled or not
|
||||
+ */
|
||||
+ public boolean isEnabled() {
|
||||
+ return enabled;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ @Override
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ @NotNull
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+}
|
|
@ -1,29 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Sun, 17 Mar 2019 23:04:30 +0000
|
||||
Subject: [PATCH] Annotation Test changes
|
||||
|
||||
|
||||
diff --git a/src/test/java/org/bukkit/AnnotationTest.java b/src/test/java/org/bukkit/AnnotationTest.java
|
||||
index f82f085ab9069abce10c2339446ef0d0bec8888c..15ae70ae69b27712d68270866d7940ff618c9fbe 100644
|
||||
--- a/src/test/java/org/bukkit/AnnotationTest.java
|
||||
+++ b/src/test/java/org/bukkit/AnnotationTest.java
|
||||
@@ -46,7 +46,17 @@ public class AnnotationTest {
|
||||
"org/bukkit/util/io/Wrapper",
|
||||
"org/bukkit/plugin/java/PluginClassLoader",
|
||||
// Generic functional interface
|
||||
- "org/bukkit/util/Consumer"
|
||||
+ "org/bukkit/util/Consumer",
|
||||
+ // Paper start
|
||||
+ // Timings history is broken in terms of nullability due to guavas Function defining that the param is NonNull
|
||||
+ "co/aikar/timings/TimingHistory$2",
|
||||
+ "co/aikar/timings/TimingHistory$2$1",
|
||||
+ "co/aikar/timings/TimingHistory$2$1$1",
|
||||
+ "co/aikar/timings/TimingHistory$2$1$2",
|
||||
+ "co/aikar/timings/TimingHistory$3",
|
||||
+ "co/aikar/timings/TimingHistory$4",
|
||||
+ "co/aikar/timings/TimingHistoryEntry$1"
|
||||
+ // Paper end
|
||||
};
|
||||
|
||||
@Test
|
|
@ -1,68 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Fri, 18 Jan 2019 00:08:15 -0500
|
||||
Subject: [PATCH] Fix Custom Shapeless Custom Crafting Recipes
|
||||
|
||||
Mojang implemented Shapeless different than Shaped
|
||||
|
||||
This made the Bukkit RecipeChoice API not work for Shapeless.
|
||||
|
||||
This reimplements vanilla logic using the same test logic as Shaped
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipe.java b/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipe.java
|
||||
index 4e1159b3188d39c998e6887c2846209c10b701f9..6b960f0a31175bcfd8d477ee5b3c4d783303cdd5 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipe.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipe.java
|
||||
@@ -76,16 +76,49 @@ public class ShapelessRecipe implements CraftingRecipe {
|
||||
StackedContents autorecipestackmanager = new StackedContents();
|
||||
int i = 0;
|
||||
|
||||
+ // Paper start
|
||||
+ java.util.List<ItemStack> providedItems = new java.util.ArrayList<>();
|
||||
+ co.aikar.util.Counter<ItemStack> matchedProvided = new co.aikar.util.Counter<>();
|
||||
+ co.aikar.util.Counter<Ingredient> matchedIngredients = new co.aikar.util.Counter<>();
|
||||
+ // Paper end
|
||||
for (int j = 0; j < inventory.getContainerSize(); ++j) {
|
||||
ItemStack itemstack = inventory.getItem(j);
|
||||
|
||||
if (!itemstack.isEmpty()) {
|
||||
- ++i;
|
||||
- autorecipestackmanager.accountStack(itemstack, 1);
|
||||
+ // Paper start
|
||||
+ itemstack = itemstack.copy();
|
||||
+ providedItems.add(itemstack);
|
||||
+ for (Ingredient ingredient : ingredients) {
|
||||
+ if (ingredient.test(itemstack)) {
|
||||
+ matchedProvided.increment(itemstack);
|
||||
+ matchedIngredients.increment(ingredient);
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
}
|
||||
|
||||
- return i == this.ingredients.size() && autorecipestackmanager.canCraft(this, (IntList) null);
|
||||
+ // Paper start
|
||||
+ if (matchedProvided.isEmpty() || matchedIngredients.isEmpty()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ java.util.List<Ingredient> ingredients = new java.util.ArrayList<>(this.ingredients);
|
||||
+ providedItems.sort(java.util.Comparator.comparingInt((ItemStack c) -> (int) matchedProvided.getCount(c)).reversed());
|
||||
+ ingredients.sort(java.util.Comparator.comparingInt((Ingredient c) -> (int) matchedIngredients.getCount(c)));
|
||||
+
|
||||
+ PROVIDED:
|
||||
+ for (ItemStack provided : providedItems) {
|
||||
+ for (Iterator<Ingredient> itIngredient = ingredients.iterator(); itIngredient.hasNext(); ) {
|
||||
+ Ingredient ingredient = itIngredient.next();
|
||||
+ if (ingredient.test(provided)) {
|
||||
+ itIngredient.remove();
|
||||
+ continue PROVIDED;
|
||||
+ }
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+ return ingredients.isEmpty();
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
public ItemStack assemble(CraftingContainer inventory) {
|
|
@ -1,51 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Wed, 27 Feb 2019 22:18:40 -0500
|
||||
Subject: [PATCH] Limit Client Sign length more
|
||||
|
||||
modified clients can send more data from the client
|
||||
to the server and it would get stored on the sign as sent.
|
||||
|
||||
Mojang has a limit of 384 which is much higher than reasonable.
|
||||
|
||||
the client can barely render around 16 characters as-is, but formatting
|
||||
codes can get it to be more than 16 actual length.
|
||||
|
||||
Set a limit of 80 which should give an average of 16 characters 2
|
||||
sets of legacy formatting codes which should be plenty for all uses.
|
||||
|
||||
This does not strip any existing data from the NBT as plugins
|
||||
may use this for storing data out of the rendered area.
|
||||
|
||||
it only impacts data sent from the client.
|
||||
|
||||
Set -DPaper.maxSignLength=XX to change limit or -1 to disable
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 2ea1e58cf721a8ae339cbfd6192f3312061249ba..b9f9314befff581e70ae7d8d4eab9040e4e4d26d 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -254,6 +254,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
|
||||
private int aboveGroundVehicleTickCount;
|
||||
private int receivedMovePacketCount;
|
||||
private int knownMovePacketCount;
|
||||
+ private static final int MAX_SIGN_LINE_LENGTH = Integer.getInteger("Paper.maxSignLength", 80);
|
||||
private static final long KEEPALIVE_LIMIT = Long.getLong("paper.playerconnection.keepalive", 30) * 1000; // Paper - provide property to set keepalive limit
|
||||
|
||||
public ServerGamePacketListenerImpl(MinecraftServer server, Connection connection, ServerPlayer player) {
|
||||
@@ -2848,6 +2849,15 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
|
||||
|
||||
for (int i = 0; i < signText.size(); ++i) {
|
||||
TextFilter.FilteredText currentLine = signText.get(i);
|
||||
+ // Paper start - cap line length - modified clients can send longer data than normal
|
||||
+ if (MAX_SIGN_LINE_LENGTH > 0 && currentLine.getRaw().length() > MAX_SIGN_LINE_LENGTH) {
|
||||
+ // This handles multibyte characters as 1
|
||||
+ int offset = currentLine.getRaw().codePoints().limit(MAX_SIGN_LINE_LENGTH).map(Character::charCount).sum();
|
||||
+ if (offset < currentLine.getRaw().length()) {
|
||||
+ signText.set(i, currentLine = net.minecraft.server.network.TextFilter.FilteredText.passThrough(currentLine.getRaw().substring(0, offset))); // this will break any filtering, but filtering is NYI as of 1.17
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
if (this.player.isTextFilteringEnabled()) {
|
||||
lines.add(net.kyori.adventure.text.Component.text(SharedConstants.filterText(currentLine.getFiltered())));
|
|
@ -1,29 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sat, 2 Mar 2019 11:11:29 -0500
|
||||
Subject: [PATCH] Don't check ConvertSigns boolean every sign save
|
||||
|
||||
property lookups arent super cheap. they synchronize, validate
|
||||
and check security managers.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java
|
||||
index 589fbdd5c86655244aa92a42e5f45747b5c5026e..9b5d11ece006d7aa893360a84ba652c666517ac1 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java
|
||||
@@ -26,6 +26,7 @@ import net.minecraft.world.phys.Vec2;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class SignBlockEntity extends BlockEntity implements CommandSource { // CraftBukkit - implements
|
||||
+ private static final boolean CONVERT_LEGACY_SIGNS = Boolean.getBoolean("convertLegacySigns"); // Paper
|
||||
|
||||
public static final int LINES = 4;
|
||||
private static final String[] RAW_TEXT_FIELD_NAMES = new String[]{"Text1", "Text2", "Text3", "Text4"};
|
||||
@@ -66,7 +67,7 @@ public class SignBlockEntity extends BlockEntity implements CommandSource { // C
|
||||
}
|
||||
|
||||
// CraftBukkit start
|
||||
- if (Boolean.getBoolean("convertLegacySigns")) {
|
||||
+ if (CONVERT_LEGACY_SIGNS) { // Paper
|
||||
nbt.putBoolean("Bukkit.isConverted", true);
|
||||
}
|
||||
// CraftBukkit end
|
|
@ -1,323 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Wed, 6 May 2020 04:53:35 -0400
|
||||
Subject: [PATCH] Optimize Network Manager and add advanced packet support
|
||||
|
||||
Adds ability for 1 packet to bundle other packets to follow it
|
||||
Adds ability for a packet to delay sending more packets until a state is ready.
|
||||
|
||||
Removes synchronization from sending packets
|
||||
Removes processing packet queue off of main thread
|
||||
- for the few cases where it is allowed, order is not necessary nor
|
||||
should it even be happening concurrently in first place (handshaking/login/status)
|
||||
|
||||
Ensures packets sent asynchronously are dispatched on main thread
|
||||
|
||||
This helps ensure safety for ProtocolLib as packet listeners
|
||||
are commonly accessing world state. This will allow you to schedule
|
||||
a packet to be sent async, but itll be dispatched sync for packet
|
||||
listeners to process.
|
||||
|
||||
This should solve some deadlock risks
|
||||
|
||||
Also adds Netty Channel Flush Consolidation to reduce the amount of flushing
|
||||
|
||||
Also avoids spamming closed channel exception by rechecking closed state in dispatch
|
||||
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 b96ef2374b689ad715ce3b3a7c0b599a56b4c2d1..a3bfc12e34754dc5f8f53b968451a07f3a0ab496 100644
|
||||
--- a/src/main/java/net/minecraft/network/Connection.java
|
||||
+++ b/src/main/java/net/minecraft/network/Connection.java
|
||||
@@ -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");
|
||||
+ // Optimize network
|
||||
+ public boolean isPending = true;
|
||||
+ public boolean queueImmunity = false;
|
||||
+ public ConnectionProtocol protocol;
|
||||
// Paper end
|
||||
|
||||
public Connection(PacketFlow side) {
|
||||
@@ -110,6 +114,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
}
|
||||
|
||||
public void setProtocol(ConnectionProtocol state) {
|
||||
+ protocol = state; // Paper
|
||||
this.channel.attr(Connection.ATTRIBUTE_PROTOCOL).set(state);
|
||||
this.channel.config().setAutoRead(true);
|
||||
Connection.LOGGER.debug("Enabled auto read");
|
||||
@@ -186,19 +191,87 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
Validate.notNull(listener, "packetListener", new Object[0]);
|
||||
this.packetListener = listener;
|
||||
}
|
||||
+ // Paper start
|
||||
+ public net.minecraft.server.level.ServerPlayer getPlayer() {
|
||||
+ if (packetListener instanceof ServerGamePacketListenerImpl) {
|
||||
+ return ((ServerGamePacketListenerImpl) packetListener).player;
|
||||
+ } else {
|
||||
+ return null;
|
||||
+ }
|
||||
+ }
|
||||
+ private static class InnerUtil { // Attempt to hide these methods from ProtocolLib so it doesn't accidently pick them up.
|
||||
+ private static java.util.List<Packet> buildExtraPackets(Packet packet) {
|
||||
+ java.util.List<Packet> extra = packet.getExtraPackets();
|
||||
+ if (extra == null || extra.isEmpty()) {
|
||||
+ return null;
|
||||
+ }
|
||||
+ java.util.List<Packet> ret = new java.util.ArrayList<>(1 + extra.size());
|
||||
+ buildExtraPackets0(extra, ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ private static void buildExtraPackets0(java.util.List<Packet> extraPackets, java.util.List<Packet> into) {
|
||||
+ for (Packet extra : extraPackets) {
|
||||
+ into.add(extra);
|
||||
+ java.util.List<Packet> extraExtra = extra.getExtraPackets();
|
||||
+ if (extraExtra != null && !extraExtra.isEmpty()) {
|
||||
+ buildExtraPackets0(extraExtra, into);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper start
|
||||
+ private static boolean canSendImmediate(Connection networkManager, Packet<?> packet) {
|
||||
+ return networkManager.isPending || networkManager.protocol != ConnectionProtocol.PLAY ||
|
||||
+ 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
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
public void send(Packet<?> packet) {
|
||||
this.send(packet, (GenericFutureListener) null);
|
||||
}
|
||||
|
||||
public void send(Packet<?> packet, @Nullable GenericFutureListener<? extends Future<? super Void>> callback) {
|
||||
- if (this.isConnected()) {
|
||||
- this.flushQueue();
|
||||
+ // Paper start - handle oversized packets better
|
||||
+ boolean connected = this.isConnected();
|
||||
+ if (!connected && !preparing) {
|
||||
+ return; // Do nothing
|
||||
+ }
|
||||
+ packet.onPacketDispatch(getPlayer());
|
||||
+ if (connected && (InnerUtil.canSendImmediate(this, packet) || (
|
||||
+ net.minecraft.server.MCUtil.isMainThread() && packet.isReady() && this.queue.isEmpty() &&
|
||||
+ (packet.getExtraPackets() == null || packet.getExtraPackets().isEmpty())
|
||||
+ ))) {
|
||||
this.sendPacket(packet, callback);
|
||||
- } else {
|
||||
- this.queue.add(new Connection.PacketHolder(packet, callback));
|
||||
+ return;
|
||||
}
|
||||
+ // write the packets to the queue, then flush - antixray hooks there already
|
||||
+ java.util.List<Packet> extraPackets = InnerUtil.buildExtraPackets(packet);
|
||||
+ boolean hasExtraPackets = extraPackets != null && !extraPackets.isEmpty();
|
||||
+ if (!hasExtraPackets) {
|
||||
+ this.queue.add(new Connection.PacketHolder(packet, callback));
|
||||
+ } 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.flushQueue();
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ net.minecraft.server.level.ServerPlayer player = getPlayer();
|
||||
+ 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 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 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 flushQueue() { // void -> boolean
|
||||
+ if (!isConnected()) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ if (net.minecraft.server.MCUtil.isMainThread()) {
|
||||
+ return processQueue();
|
||||
+ } else if (isPending) {
|
||||
+ // Should only happen during login/status stages
|
||||
synchronized (this.queue) {
|
||||
- Connection.PacketHolder networkmanager_queuedpacket;
|
||||
-
|
||||
- while ((networkmanager_queuedpacket = (Connection.PacketHolder) this.queue.poll()) != null) {
|
||||
- this.sendPacket(networkmanager_queuedpacket.packet, networkmanager_queuedpacket.listener);
|
||||
- }
|
||||
+ return this.processQueue();
|
||||
+ }
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+ private boolean processQueue() {
|
||||
+ if (this.queue.isEmpty()) return true;
|
||||
+ // If we are on main, we are safe here in that nothing else should be processing queue off main anymore
|
||||
+ // 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()) {
|
||||
+ PacketHolder queued = iterator.next(); // poll -> peek
|
||||
+
|
||||
+ // Fix NPE (Spigot bug caused by handleDisconnection())
|
||||
+ if (queued == null) {
|
||||
+ return true;
|
||||
+ }
|
||||
|
||||
+ Packet<?> packet = queued.packet;
|
||||
+ if (!packet.isReady()) {
|
||||
+ return false;
|
||||
+ } else {
|
||||
+ iterator.remove();
|
||||
+ this.sendPacket(packet, queued.listener);
|
||||
}
|
||||
}
|
||||
+ return true;
|
||||
}
|
||||
+ // Paper end
|
||||
|
||||
public void tick() {
|
||||
this.flushQueue();
|
||||
@@ -289,9 +408,22 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
return this.address;
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ public void clearPacketQueue() {
|
||||
+ net.minecraft.server.level.ServerPlayer player = getPlayer();
|
||||
+ queue.forEach(queuedPacket -> {
|
||||
+ Packet<?> packet = queuedPacket.packet;
|
||||
+ if (packet.hasFinishListener()) {
|
||||
+ packet.onPacketDispatchFinish(player, null);
|
||||
+ }
|
||||
+ });
|
||||
+ queue.clear();
|
||||
+ }
|
||||
+ // Paper end
|
||||
public void disconnect(Component disconnectReason) {
|
||||
// Spigot Start
|
||||
this.preparing = false;
|
||||
+ clearPacketQueue(); // Paper
|
||||
// Spigot End
|
||||
if (this.channel.isOpen()) {
|
||||
this.channel.close(); // We can't wait as this may be called from an event loop.
|
||||
@@ -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");
|
||||
+ //Connection.LOGGER.warn("handleDisconnection() called twice"); // Paper - Do not log useless message
|
||||
} else {
|
||||
this.disconnectionHandled = true;
|
||||
if (this.getDisconnectedReason() != null) {
|
||||
@@ -417,7 +549,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
} else if (this.getPacketListener() != null) {
|
||||
this.getPacketListener().onDisconnect(new TranslatableComponent("multiplayer.disconnect.generic"));
|
||||
}
|
||||
- this.queue.clear(); // Free up packet queue.
|
||||
+ clearPacketQueue(); // Paper
|
||||
// Paper start - Add PlayerConnectionCloseEvent
|
||||
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 74bfe0d3942259c45702b099efdc4e101a4e3022..e8fcd56906d26f6dc87959e32c4c7c78cfea9658 100644
|
||||
--- a/src/main/java/net/minecraft/network/protocol/Packet.java
|
||||
+++ b/src/main/java/net/minecraft/network/protocol/Packet.java
|
||||
@@ -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 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 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(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 abcd335f5577dae6d613e5e0dd2656e1ab3ee9f0..4e08fdf47fd201c26223fc8efb0ef4f6e884f8c7 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java
|
||||
@@ -63,10 +63,12 @@ public class ServerConnectionListener {
|
||||
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 final void addPending() {
|
||||
Connection manager = null;
|
||||
while ((manager = pending.poll()) != null) {
|
||||
connections.add(manager);
|
||||
+ manager.isPending = false;
|
||||
}
|
||||
}
|
||||
// Paper end
|
||||
@@ -101,6 +103,7 @@ public class ServerConnectionListener {
|
||||
;
|
||||
}
|
||||
|
||||
+ if (!disableFlushConsolidation) channel.pipeline().addFirst(new io.netty.handler.flush.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);
|
|
@ -1,50 +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 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);
|
|
@ -1,36 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sat, 2 Mar 2019 16:12:35 -0500
|
||||
Subject: [PATCH] MC-145260: Fix Whitelist On/Off inconsistency
|
||||
|
||||
mojang stored whitelist state in 2 places (Whitelist Object, PlayerList)
|
||||
|
||||
some things checked PlayerList, some checked object. This moves
|
||||
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 f8827ca44a6e099d0a8a05265b01e6f5da3567e0..b2e418db3b8b1b88b92234a9fc913a09d1325793 100644
|
||||
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
@@ -64,6 +64,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;
|
||||
+import net.minecraft.server.MCUtil;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.PlayerAdvancements;
|
||||
import net.minecraft.server.ServerScoreboard;
|
||||
@@ -1005,9 +1006,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); // Paper - use isUsingWhitelist()
|
||||
final com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent event;
|
||||
- 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) {
|
|
@ -1,19 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <zach@zachbr.io>
|
||||
Date: Mon, 4 Mar 2019 02:23:28 -0500
|
||||
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 96d172c428c6293b346201159422e2a581e350d9..4f328c3281663a55eef879604d713ff38d797298 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java
|
||||
@@ -225,6 +225,7 @@ public class Zombie extends Monster {
|
||||
++this.inWaterTime;
|
||||
if (this.inWaterTime >= 600) {
|
||||
this.startUnderWaterConversion(300);
|
||||
+ this.lastTick = MinecraftServer.currentTick; // Paper - Make sure this is set at start of process - GH-1887
|
||||
}
|
||||
} else {
|
||||
this.inWaterTime = -1;
|
|
@ -1,18 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Mark Vainomaa <mikroskeem@mikroskeem.eu>
|
||||
Date: Wed, 13 Mar 2019 20:08:09 +0200
|
||||
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 b2e418db3b8b1b88b92234a9fc913a09d1325793..bc73d5052611dba90c2d9c86854447be6a31fdac 100644
|
||||
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
@@ -1124,6 +1124,7 @@ public abstract class PlayerList {
|
||||
}
|
||||
|
||||
public void setUsingWhiteList(boolean whitelistEnabled) {
|
||||
+ new com.destroystokyo.paper.event.server.WhitelistToggleEvent(whitelistEnabled).callEvent();
|
||||
this.doWhiteList = whitelistEnabled;
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: kashike <kashike@vq.lc>
|
||||
Date: Wed, 20 Mar 2019 21:19:29 -0700
|
||||
Subject: [PATCH] Use proper max length when serialising BungeeCord text
|
||||
component
|
||||
|
||||
|
||||
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 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
|
||||
@@ -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 final Component message;
|
||||
public net.kyori.adventure.text.Component adventure$message; // Paper
|
||||
public net.md_5.bungee.api.chat.BaseComponent[] components; // Spigot
|
||||
@@ -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.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.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
|
||||
} else {
|
Loading…
Add table
Add a link
Reference in a new issue