From f1a92f03db2f216e289e7328023f2527bb6d4905 Mon Sep 17 00:00:00 2001 From: Shane Freeder Date: Tue, 2 Oct 2018 06:38:51 +0100 Subject: [PATCH] Cleanup tab completion During testing, I could not find any case of TabCompleteEvent firing, however, upon reinspection of the code, and additional testing, this appears to work fine without any changes on our part. --- .../0219-AsyncTabCompleteEvent.patch | 69 +++++-------------- ...-allowed-colored-signs-to-be-created.patch | 6 +- .../0283-InventoryCloseEvent-Reason-API.patch | 6 +- ...nventory-when-cancelling-PlayerInter.patch | 6 +- ...nd-make-tab-spam-limits-configurable.patch | 10 +-- 5 files changed, 32 insertions(+), 65 deletions(-) diff --git a/Spigot-Server-Patches/0219-AsyncTabCompleteEvent.patch b/Spigot-Server-Patches/0219-AsyncTabCompleteEvent.patch index 5e91ad604..fa05162ca 100644 --- a/Spigot-Server-Patches/0219-AsyncTabCompleteEvent.patch +++ b/Spigot-Server-Patches/0219-AsyncTabCompleteEvent.patch @@ -1,4 +1,4 @@ -From 83c1d973643f20430da29f935cfb205aa377f1e4 Mon Sep 17 00:00:00 2001 +From 8a9e74f57f7f774225415163916c8f12b6efcb4d Mon Sep 17 00:00:00 2001 From: Aikar Date: Sun, 26 Nov 2017 13:19:58 -0500 Subject: [PATCH] AsyncTabCompleteEvent @@ -14,18 +14,10 @@ completion, such as offline players. Also adds isCommand and getLocation to the sync TabCompleteEvent diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java -index 7270638f4a..3e8db87b88 100644 +index 62b7f24b5a..d44ac990b4 100644 --- a/src/main/java/net/minecraft/server/PlayerConnection.java +++ b/src/main/java/net/minecraft/server/PlayerConnection.java -@@ -10,6 +10,7 @@ import io.netty.util.concurrent.Future; - import io.netty.util.concurrent.GenericFutureListener; - import java.util.Collections; - import java.util.Iterator; -+import java.util.List; - import java.util.Set; - import java.util.function.Consumer; - import javax.annotation.Nullable; -@@ -509,10 +510,10 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { +@@ -508,10 +508,10 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { } public void a(PacketPlayInTabComplete packetplayintabcomplete) { @@ -38,12 +30,11 @@ index 7270638f4a..3e8db87b88 100644 return; } // CraftBukkit end -@@ -522,11 +523,57 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { +@@ -521,12 +521,34 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { stringreader.skip(); } -- ParseResults parseresults = this.minecraftServer.getCommandDispatcher().a().parse(stringreader, this.player.getCommandListener()); -+ // Paper start ++ // Paper start - async tab completion + com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event; + java.util.List completions = new java.util.ArrayList<>(); + String buffer = packetplayintabcomplete.c(); @@ -53,53 +44,29 @@ index 7270638f4a..3e8db87b88 100644 + completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.getCompletions(); + // If the event isn't handled, we can assume that we have no completions, and so we'll ask the server + if (!event.isHandled()) { -+ if (!event.isCancelled() && org.bukkit.event.server.TabCompleteEvent.getHandlerList().getRegisteredListeners().length > 0) { -+ java.util.List finalCompletions = completions; -+ Waitable> syncCompletions = new Waitable>() { -+ @Override -+ protected java.util.List evaluate() { -+ org.bukkit.event.server.TabCompleteEvent syncEvent = new org.bukkit.event.server.TabCompleteEvent(PlayerConnection.this.getPlayer(), buffer, finalCompletions, true, null); -+ return syncEvent.callEvent() ? syncEvent.getCompletions() : com.google.common.collect.ImmutableList.of(); -+ } -+ }; -+ server.getServer().processQueue.add(syncCompletions); -+ try { -+ completions = syncCompletions.get(); -+ } catch (InterruptedException | ExecutionException e1) { -+ e1.printStackTrace(); -+ } ++ if (!event.isCancelled()) { ++ // Paper end - async tab completion + ParseResults parseresults = this.minecraftServer.getCommandDispatcher().a().parse(stringreader, this.player.getCommandListener()); + + this.minecraftServer.getCommandDispatcher().a().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> { + if (((Suggestions) suggestions).isEmpty()) return; // CraftBukkit - don't send through empty suggestions - prevents [] from showing for plugins with nothing more to offer +- this.networkManager.sendPacket(new PacketPlayOutTabComplete(packetplayintabcomplete.b(), (Suggestions) suggestions)); // CraftBukkit - decompile error +- }); ++ this.networkManager.sendPacket(new PacketPlayOutTabComplete(packetplayintabcomplete.b(), (Suggestions) suggestions)); // CraftBukkit - decompile error ++ }); + } -+ java.util.List otherSuggestions = completions; -+ minecraftServer.postToMainThread(() -> sendSuggestions(packetplayintabcomplete, stringreader, otherSuggestions)); -+ return; ++ // Paper start - async tab completion + } else if (!completions.isEmpty()) { + com.mojang.brigadier.suggestion.SuggestionsBuilder suggestionsBuilder = new com.mojang.brigadier.suggestion.SuggestionsBuilder(packetplayintabcomplete.c(), stringreader.getTotalLength()); + completions.forEach(suggestionsBuilder::suggest); + + player.playerConnection.sendPacket(new PacketPlayOutTabComplete(packetplayintabcomplete.b(), suggestionsBuilder.build())); + } - -- this.minecraftServer.getCommandDispatcher().a().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> { -- if (((Suggestions) suggestions).isEmpty()) return; // CraftBukkit - don't send through empty suggestions - prevents [] from showing for plugins with nothing more to offer -- this.networkManager.sendPacket(new PacketPlayOutTabComplete(packetplayintabcomplete.b(), (Suggestions) suggestions)); // CraftBukkit - decompile error -+ } -+ public void sendSuggestions(PacketPlayInTabComplete packetplayintabcomplete, StringReader reader, List otherSuggestions) { ++ // Paper end - async tab completion + -+ ParseResults parseresults = this.minecraftServer.getCommandDispatcher().a().parse(reader, this.player.getCommandListener()); -+ //noinspection unchecked -+ java.util.concurrent.CompletableFuture completionSuggestions = this.minecraftServer.getCommandDispatcher().a().getCompletionSuggestions(parseresults); -+ completionSuggestions.thenAccept((Suggestions suggestions) -> { -+ if (otherSuggestions != null && !otherSuggestions.isEmpty()) { -+ com.mojang.brigadier.suggestion.SuggestionsBuilder builder = new com.mojang.brigadier.suggestion.SuggestionsBuilder(packetplayintabcomplete.c(), reader.getTotalLength()); -+ otherSuggestions.forEach(builder::suggest); -+ suggestions.getList().addAll(builder.build().getList()); -+ } -+ // Paper end -+ if (suggestions.isEmpty()) return; // CraftBukkit - don't send through empty suggestions - prevents [] from showing for plugins with nothing more to offer -+ this.networkManager.sendPacket(new PacketPlayOutTabComplete(packetplayintabcomplete.b(), suggestions)); // CraftBukkit - decompile error - }); } + public void a(PacketPlayInSetCommandBlock packetplayinsetcommandblock) { diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java index 74e466d1f6..0e582e4e5c 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java diff --git a/Spigot-Server-Patches/0253-Fix-exploit-that-allowed-colored-signs-to-be-created.patch b/Spigot-Server-Patches/0253-Fix-exploit-that-allowed-colored-signs-to-be-created.patch index 14a3ae171..6c462f039 100644 --- a/Spigot-Server-Patches/0253-Fix-exploit-that-allowed-colored-signs-to-be-created.patch +++ b/Spigot-Server-Patches/0253-Fix-exploit-that-allowed-colored-signs-to-be-created.patch @@ -1,14 +1,14 @@ -From 56d6b35951db8bca64c6180c17622e6449451a00 Mon Sep 17 00:00:00 2001 +From 32ca5f96dc4dfba8b85020cd0157d086733cc5e6 Mon Sep 17 00:00:00 2001 From: 0x22 <0x22@futureclient.net> Date: Thu, 26 Apr 2018 04:41:11 -0400 Subject: [PATCH] Fix exploit that allowed colored signs to be created diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java -index 3e8db87b88..7c183ff6fa 100644 +index 7861097f87..dfe7921a4a 100644 --- a/src/main/java/net/minecraft/server/PlayerConnection.java +++ b/src/main/java/net/minecraft/server/PlayerConnection.java -@@ -2521,7 +2521,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { +@@ -2493,7 +2493,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { String[] lines = new String[4]; for (int i = 0; i < astring.length; ++i) { diff --git a/Spigot-Server-Patches/0283-InventoryCloseEvent-Reason-API.patch b/Spigot-Server-Patches/0283-InventoryCloseEvent-Reason-API.patch index 3ce1a906b..ab5f6ab4e 100644 --- a/Spigot-Server-Patches/0283-InventoryCloseEvent-Reason-API.patch +++ b/Spigot-Server-Patches/0283-InventoryCloseEvent-Reason-API.patch @@ -1,4 +1,4 @@ -From 004b2a8aaf9d8905410907b4ab247ddeb159ac92 Mon Sep 17 00:00:00 2001 +From ac07641c46fb82792fac6733c44147ef00f4e88d Mon Sep 17 00:00:00 2001 From: Aikar Date: Tue, 3 Jul 2018 21:56:23 -0400 Subject: [PATCH] InventoryCloseEvent Reason API @@ -110,10 +110,10 @@ index 3644fde3bb..68f5842cfe 100644 this.m(); } diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java -index 7c183ff6fa..7704a2bc6a 100644 +index dfe7921a4a..fe967bac5b 100644 --- a/src/main/java/net/minecraft/server/PlayerConnection.java +++ b/src/main/java/net/minecraft/server/PlayerConnection.java -@@ -2057,7 +2057,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { +@@ -2029,7 +2029,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { PlayerConnectionUtils.ensureMainThread(packetplayinclosewindow, this, this.player.getWorldServer()); if (this.player.isFrozen()) return; // CraftBukkit diff --git a/Spigot-Server-Patches/0287-Refresh-player-inventory-when-cancelling-PlayerInter.patch b/Spigot-Server-Patches/0287-Refresh-player-inventory-when-cancelling-PlayerInter.patch index 66236e5d0..c5f73fbaf 100644 --- a/Spigot-Server-Patches/0287-Refresh-player-inventory-when-cancelling-PlayerInter.patch +++ b/Spigot-Server-Patches/0287-Refresh-player-inventory-when-cancelling-PlayerInter.patch @@ -1,4 +1,4 @@ -From ba1cb9f73490d3b1d748e8ecd40c5ddc54a8b271 Mon Sep 17 00:00:00 2001 +From 53226e517933eddd9d6db482e86d5ca33a604832 Mon Sep 17 00:00:00 2001 From: Minecrell Date: Fri, 13 Jul 2018 14:54:43 +0200 Subject: [PATCH] Refresh player inventory when cancelling @@ -16,10 +16,10 @@ Refresh the player inventory when PlayerInteractEntityEvent is cancelled to avoid this problem. diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java -index 7704a2bc6a..ff2f3d9971 100644 +index fe967bac5b..5781f4d2ce 100644 --- a/src/main/java/net/minecraft/server/PlayerConnection.java +++ b/src/main/java/net/minecraft/server/PlayerConnection.java -@@ -1971,6 +1971,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { +@@ -1943,6 +1943,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { } if (event.isCancelled()) { diff --git a/Spigot-Server-Patches/0319-Break-up-and-make-tab-spam-limits-configurable.patch b/Spigot-Server-Patches/0319-Break-up-and-make-tab-spam-limits-configurable.patch index cbb41e744..f07114b2c 100644 --- a/Spigot-Server-Patches/0319-Break-up-and-make-tab-spam-limits-configurable.patch +++ b/Spigot-Server-Patches/0319-Break-up-and-make-tab-spam-limits-configurable.patch @@ -1,4 +1,4 @@ -From a3955c05b1cd607ec7b32ab33ef150344e2ead37 Mon Sep 17 00:00:00 2001 +From 562e223df4bdb81d7e94dcaf9953da1c81dc61e3 Mon Sep 17 00:00:00 2001 From: Shane Freeder Date: Sun, 29 Jul 2018 05:02:15 +0100 Subject: [PATCH] Break up and make tab spam limits configurable @@ -45,10 +45,10 @@ index b32e75ae9a..3419847e34 100644 + } } diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java -index ff2f3d9971..7768b5898a 100644 +index 5781f4d2ce..d1ad7728e3 100644 --- a/src/main/java/net/minecraft/server/PlayerConnection.java +++ b/src/main/java/net/minecraft/server/PlayerConnection.java -@@ -78,6 +78,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { +@@ -77,6 +77,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { // CraftBukkit start - multithreaded fields private volatile int chatThrottle; private static final AtomicIntegerFieldUpdater chatSpamField = AtomicIntegerFieldUpdater.newUpdater(PlayerConnection.class, "chatThrottle"); @@ -56,7 +56,7 @@ index ff2f3d9971..7768b5898a 100644 // CraftBukkit end private int j; private final IntHashMap k = new IntHashMap(); -@@ -207,6 +208,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { +@@ -206,6 +207,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { this.minecraftServer.methodProfiler.e(); // CraftBukkit start for (int spam; (spam = this.chatThrottle) > 0 && !chatSpamField.compareAndSet(this, spam, spam - 1); ) ; @@ -64,7 +64,7 @@ index ff2f3d9971..7768b5898a 100644 /* Use thread-safe field access instead if (this.chatThrottle > 0) { --this.chatThrottle; -@@ -512,7 +514,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { +@@ -511,7 +513,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { public void a(PacketPlayInTabComplete packetplayintabcomplete) { // PlayerConnectionUtils.ensureMainThread(packetplayintabcomplete, this, this.player.getWorldServer()); // Paper - run this async // CraftBukkit start