Compare commits

...

10 Commits

Author SHA1 Message Date
Yannick Lamprecht 96fdafd935
Player Entity Tracking Events (#4722) 2022-12-03 16:46:38 -06:00
Jake Potrebic ec6a9a3e47
Updated Upstream (Bukkit/CraftBukkit) (#8604)
Upstream has released updates that appear to apply and compile correctly. This update has not been tested by PaperMC and as with ANY update, please do your own testing

Bukkit Changes:
38866413 SPIGOT-6765: Pass WorldInfo, Random and coordinates to ChunkGenerator should methods

CraftBukkit Changes:
f3dab3a48 SPIGOT-7191: TNT minecart explosions crash the server
b5aa0bed9 SPIGOT-7184: ExplosionPrimeEvent not called for ExplosiveMinecart
e7aab5493 SPIGOT-6765: Pass WorldInfo, Random and coordinates to ChunkGenerator should methods
2022-12-03 10:19:09 -08:00
Bjarne Koll 425baed78f
Fully deserialise persistent anger post async load (#8560)
The modified patch prevents entity loading off the main thread when
entities are initially loaded.

However, the initial loading of an entity is not the only time the
Entity#readAdditionalSaveData method is called. Commands like /data also
invoke the method (through Entity#load) to update an entities data
without completely re-creating it.

This however breaks with the current patch, as the patch moves parts of
the entity lookup for persistent anger deserialisation into the first
tick of an entity (which obviously is only called once and hence not
re-run when an already ticking entity is modified as laid out above).

This change actively runs the now split logic for deserialisation again
if the entity has already ticked its first tick. This way, initial
deserialisation is still split into one off thread and the first tick
parts, but following main thread deserialisations can happen completely
inside Entity#readAdditionalSaveData is called.
2022-12-02 18:09:41 +01:00
Jake Potrebic c40f8d59a9
Sync offhand slot in menus (#7341) 2022-12-01 13:01:49 -08:00
Jake Potrebic 41ab602f47
[ci skip] couple more fixes for build pr jar label (#8599) 2022-11-30 12:45:27 -08:00
Jason Penilla 54daefa0ca
Fix whitespace error in recent patch 2022-11-28 11:10:26 -07:00
Lulu13022002 8796175d79
Handle legacy quirk in the console formatter (#8434) 2022-11-28 14:41:29 +01:00
Denery 309133e2e1
Fix preemptive connection dropping during shutdown process (#8546) 2022-11-27 11:20:31 -06:00
sandtechnology 28b4027d45
Fix packet duplicating at some points (#8566)
Due to the weakly consistent of ConcurrentLinkedQueue iterator, at some points, packet will be resent twice times or more, causing some weird behaviors (e.g. kicked for illegal movement since the same ClientboundPlayerPositionPacket was sent two times). This changes for the patch add a flag for marking if the packet was consumed to prevent such issue and ensure consistently of the packet queue.
2022-11-27 10:36:35 -06:00
Jason f1583fcd74
Add `/paper dumplisteners tofile` and increase detail of command output (#8592) 2022-11-26 10:36:11 -07:00
24 changed files with 535 additions and 106 deletions

View File

@ -53,16 +53,16 @@ jobs:
if (pull) {
result["pr"] = pull.number;
result["action"] = "paperclip";
core.info(`This is a push action but to a branch with an open PR with the build paperclip label (${JSON.stringify(result)})`);
core.notice(`This is a push action but to a branch with an open PR with the build paperclip label (${JSON.stringify(result)})`);
return result;
}
} else if (event_name === "pull_request" && event.pull_request.labels.find((l) => l.name === "build-pr-jar")) {
result["pr"] = event.pull_request.number;
result["action"] = "paperclip";
core.info(`This is a pull request action with a build paperclip label (${JSON.stringify(result)})`);
core.notice(`This is a pull request action with a build paperclip label (${JSON.stringify(result)})`);
return result;
}
core.info("This will not build a paperclip jar");
core.notice("This will not build a paperclip jar");
return result;
- name: Apply Patches
@ -72,7 +72,6 @@ jobs:
./gradlew applyPatches --stacktrace
- name: Build
if: fromJSON(steps.determine.outputs.result).action == 'build'
run: ./gradlew build --stacktrace
- name: Create Paperclip Jar

View File

@ -29,12 +29,8 @@ jobs:
const marker = `<!-- bot: ${purpose} -->`;
let new_body = data.body ? data.body.trim().split(marker)[0] : "";
if (!new_body.trim()) {
new_body += `${marker}\n${body}`
} else {
new_body += `${marker}\n---\n${body}`
}
let new_body = data.body ? data.body.trim().split(marker)[0].trim() : "";
new_body += `\n${marker}\n---\n${body}`;
core.info(`Updating the text body of PR #${issue_number} in ${owner}/${repo}`);
await github.rest.issues.update({ owner, repo, issue_number, body: new_body });

View File

@ -53,4 +53,5 @@ Nick Hensel <nickhensel25@icloud.com>
vytskalt <vytskalt@protonmail.com>
TheFruxz <cedricspitzer@outlook.de>
Kieran Wallbanks <kieran.wallbanks@gmail.com>
Denery <dorofeevij@gmail.com>
```

View File

@ -517,10 +517,10 @@ index 6bafc62e2235a6b783cbf96f4dabeeaf02bd5178..50c762d777ac90a05772501a28cacff8
cancelledCollision = cancel;
}
diff --git a/src/main/java/org/bukkit/generator/ChunkGenerator.java b/src/main/java/org/bukkit/generator/ChunkGenerator.java
index 6cb2bf60fb970b646451c02faf71a14a80e6a56b..7cf8ffb5a29d1cf382064b3aca0353a53b89fa9e 100644
index 0cc6e29a5af28e95f87f415d6b2424d4622a6f34..acba500393e1736e6081facac6ef9ab10da655de 100644
--- a/src/main/java/org/bukkit/generator/ChunkGenerator.java
+++ b/src/main/java/org/bukkit/generator/ChunkGenerator.java
@@ -514,7 +514,9 @@ public abstract class ChunkGenerator {
@@ -656,7 +656,9 @@ public abstract class ChunkGenerator {
* @param y the y location in the chunk from minHeight (inclusive) - maxHeight (exclusive)
* @param z the z location in the chunk from 0-15 inclusive
* @param material the type to set the block to
@ -530,7 +530,7 @@ index 6cb2bf60fb970b646451c02faf71a14a80e6a56b..7cf8ffb5a29d1cf382064b3aca0353a5
public void setBlock(int x, int y, int z, @NotNull MaterialData material);
/**
@@ -558,7 +560,9 @@ public abstract class ChunkGenerator {
@@ -700,7 +702,9 @@ public abstract class ChunkGenerator {
* @param yMax maximum y location (exclusive) in the chunk to set
* @param zMax maximum z location (exclusive) in the chunk to set
* @param material the type to set the blocks to
@ -540,7 +540,7 @@ index 6cb2bf60fb970b646451c02faf71a14a80e6a56b..7cf8ffb5a29d1cf382064b3aca0353a5
public void setRegion(int xMin, int yMin, int zMin, int xMax, int yMax, int zMax, @NotNull MaterialData material);
/**
@@ -599,8 +603,10 @@ public abstract class ChunkGenerator {
@@ -741,8 +745,10 @@ public abstract class ChunkGenerator {
* @param y the y location in the chunk from minHeight (inclusive) - maxHeight (exclusive)
* @param z the z location in the chunk from 0-15 inclusive
* @return the type and data of the block or the MaterialData for air if x, y or z are outside the chunk's bounds

View File

@ -61,10 +61,10 @@ index 16f631fdde4b63e0ed3162486dba684697bdffa7..a7e1d81a8a5e14f556d6b462dfba7f2e
* Creates a boss bar instance to display to players. The progress
* defaults to 1.0
diff --git a/src/main/java/org/bukkit/generator/ChunkGenerator.java b/src/main/java/org/bukkit/generator/ChunkGenerator.java
index 7cf8ffb5a29d1cf382064b3aca0353a53b89fa9e..ab972330f6219fae8d1d443b36dd9b04df22d777 100644
index acba500393e1736e6081facac6ef9ab10da655de..f1f60710ea44a078aa071dbf2d5c0ed3724e31b3 100644
--- a/src/main/java/org/bukkit/generator/ChunkGenerator.java
+++ b/src/main/java/org/bukkit/generator/ChunkGenerator.java
@@ -453,6 +453,22 @@ public abstract class ChunkGenerator {
@@ -577,6 +577,22 @@ public abstract class ChunkGenerator {
return false;
}
@ -85,5 +85,5 @@ index 7cf8ffb5a29d1cf382064b3aca0353a53b89fa9e..ab972330f6219fae8d1d443b36dd9b04
+ // Paper end
+
/**
* Data for a Chunk.
*/
* Gets if the server should generate Vanilla structures after this
* ChunkGenerator.

View File

@ -4,6 +4,88 @@ Date: Sat, 19 Nov 2022 19:46:44 +0100
Subject: [PATCH] Add /paper dumplisteners command
diff --git a/src/main/java/co/aikar/timings/TimedEventExecutor.java b/src/main/java/co/aikar/timings/TimedEventExecutor.java
index 4e6e1b8e8aeb07e34536941d2cbfc25e5cfa6c27..34e43e56ccc663e05b9cae36643e8df5eee5cb17 100644
--- a/src/main/java/co/aikar/timings/TimedEventExecutor.java
+++ b/src/main/java/co/aikar/timings/TimedEventExecutor.java
@@ -80,4 +80,10 @@ public class TimedEventExecutor implements EventExecutor {
executor.execute(listener, event);
}
}
+
+ @Override
+ @NotNull
+ public String toString() {
+ return "TimedEventExecutor['" + this.executor.toString() + "']";
+ }
}
diff --git a/src/main/java/com/destroystokyo/paper/event/executor/MethodHandleEventExecutor.java b/src/main/java/com/destroystokyo/paper/event/executor/MethodHandleEventExecutor.java
index 5b28e9b1daba7834af67dbc193dd656bedd9a994..fbebf649e893cf872be9b27091146a7c2f451aca 100644
--- a/src/main/java/com/destroystokyo/paper/event/executor/MethodHandleEventExecutor.java
+++ b/src/main/java/com/destroystokyo/paper/event/executor/MethodHandleEventExecutor.java
@@ -14,10 +14,12 @@ import org.jetbrains.annotations.NotNull;
public class MethodHandleEventExecutor implements EventExecutor {
private final Class<? extends Event> eventClass;
private final MethodHandle handle;
+ private final Method method;
public MethodHandleEventExecutor(@NotNull Class<? extends Event> eventClass, @NotNull MethodHandle handle) {
this.eventClass = eventClass;
this.handle = handle;
+ this.method = null;
}
public MethodHandleEventExecutor(@NotNull Class<? extends Event> eventClass, @NotNull Method m) {
@@ -28,6 +30,7 @@ public class MethodHandleEventExecutor implements EventExecutor {
} catch (IllegalAccessException e) {
throw new AssertionError("Unable to set accessible", e);
}
+ this.method = m;
}
@Override
@@ -39,4 +42,10 @@ public class MethodHandleEventExecutor implements EventExecutor {
SneakyThrow.sneaky(t);
}
}
+
+ @Override
+ @NotNull
+ public String toString() {
+ return "MethodHandleEventExecutor['" + this.method + "']";
+ }
}
diff --git a/src/main/java/com/destroystokyo/paper/event/executor/StaticMethodHandleEventExecutor.java b/src/main/java/com/destroystokyo/paper/event/executor/StaticMethodHandleEventExecutor.java
index c83672427324bd068ed52916f700b68446a226f6..87ea5354808dbbdefbdfc78f352a543f72a0d033 100644
--- a/src/main/java/com/destroystokyo/paper/event/executor/StaticMethodHandleEventExecutor.java
+++ b/src/main/java/com/destroystokyo/paper/event/executor/StaticMethodHandleEventExecutor.java
@@ -18,6 +18,7 @@ import org.jetbrains.annotations.NotNull;
public class StaticMethodHandleEventExecutor implements EventExecutor {
private final Class<? extends Event> eventClass;
private final MethodHandle handle;
+ private final Method method;
public StaticMethodHandleEventExecutor(@NotNull Class<? extends Event> eventClass, @NotNull Method m) {
Preconditions.checkArgument(Modifier.isStatic(m.getModifiers()), "Not a static method: %s", m);
@@ -29,6 +30,7 @@ public class StaticMethodHandleEventExecutor implements EventExecutor {
} catch (IllegalAccessException e) {
throw new AssertionError("Unable to set accessible", e);
}
+ this.method = m;
}
@Override
@@ -40,4 +42,10 @@ public class StaticMethodHandleEventExecutor implements EventExecutor {
SneakyThrow.sneaky(throwable);
}
}
+
+ @Override
+ @NotNull
+ public String toString() {
+ return "StaticMethodHandleEventExecutor['" + this.method + "']";
+ }
}
diff --git a/src/main/java/org/bukkit/event/HandlerList.java b/src/main/java/org/bukkit/event/HandlerList.java
index ed78cca71f83b296d082d0af147ca8d622c7606a..2292bd460ce2be113beb4ba6b4eb19350060f01c 100644
--- a/src/main/java/org/bukkit/event/HandlerList.java
@ -35,3 +117,61 @@ index ed78cca71f83b296d082d0af147ca8d622c7606a..2292bd460ce2be113beb4ba6b4eb1935
handlerslots = new EnumMap<EventPriority, ArrayList<RegisteredListener>>(EventPriority.class);
for (EventPriority o : EventPriority.values()) {
handlerslots.put(o, new ArrayList<RegisteredListener>());
diff --git a/src/main/java/org/bukkit/plugin/EventExecutor.java b/src/main/java/org/bukkit/plugin/EventExecutor.java
index e1860322ae0f3c35097d16767628744034941749..bdfa3b5f4ab5023d3e1b5c50bed885b6aa118a02 100644
--- a/src/main/java/org/bukkit/plugin/EventExecutor.java
+++ b/src/main/java/org/bukkit/plugin/EventExecutor.java
@@ -70,9 +70,18 @@ public interface EventExecutor {
try {
EventExecutor asmExecutor = executorClass.newInstance();
// Define a wrapper to conform to bukkit stupidity (passing in events that don't match and wrapper exception)
- return (listener, event) -> {
- if (!eventClass.isInstance(event)) return;
- asmExecutor.execute(listener, event);
+ return new EventExecutor() {
+ @Override
+ public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException {
+ if (!eventClass.isInstance(event)) return;
+ asmExecutor.execute(listener, event);
+ }
+
+ @Override
+ @NotNull
+ public String toString() {
+ return "ASMEventExecutor['" + m + "']";
+ }
};
} catch (InstantiationException | IllegalAccessException e) {
throw new AssertionError("Unable to initialize generated event executor", e);
diff --git a/src/main/java/org/bukkit/plugin/RegisteredListener.java b/src/main/java/org/bukkit/plugin/RegisteredListener.java
index 419aec56b0e3fa8bcec2ea7f340caa3456b57d00..3b3d9642a8d63798dc28f2f8df77f0466451cbff 100644
--- a/src/main/java/org/bukkit/plugin/RegisteredListener.java
+++ b/src/main/java/org/bukkit/plugin/RegisteredListener.java
@@ -78,4 +78,27 @@ public class RegisteredListener {
public boolean isIgnoringCancelled() {
return ignoreCancelled;
}
+
+ // Paper start
+ /**
+ * Get the executor for this registration.
+ *
+ * @return executor
+ */
+ @NotNull
+ public EventExecutor getExecutor() {
+ return this.executor;
+ }
+
+ @Override
+ public String toString() {
+ return "RegisteredListener{"
+ + "plugin=\"" + this.plugin.getName()
+ + "\", listener=\"" + this.listener
+ + "\", executor=\"" + this.executor
+ + "\", priority=\"" + this.priority.name() + " (" + this.priority.getSlot() + ")"
+ + "\", ignoringCancelled=" + this.ignoreCancelled
+ + "}";
+ }
+ // Paper end
}

View File

@ -0,0 +1,101 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Yannick Lamprecht <yannicklamprecht@live.de>
Date: Wed, 30 Mar 2022 18:16:37 +0200
Subject: [PATCH] Player Entity Tracking Events
diff --git a/src/main/java/io/papermc/paper/event/player/PlayerTrackEntityEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerTrackEntityEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..167be75dc616578db2df1a88f1a54b17707b3a88
--- /dev/null
+++ b/src/main/java/io/papermc/paper/event/player/PlayerTrackEntityEvent.java
@@ -0,0 +1,42 @@
+package io.papermc.paper.event.player;
+
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.Player;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.player.PlayerEvent;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Is called when a {@link Player} tracks an {@link Entity}.
+ */
+public class PlayerTrackEntityEvent extends PlayerEvent {
+
+ private static final HandlerList handlers = new HandlerList();
+ private final Entity entity;
+
+ public PlayerTrackEntityEvent(@NotNull Player player, @NotNull Entity entity) {
+ super(player);
+ this.entity = entity;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ /**
+ * Gets the entity that will be tracked
+ *
+ * @return the entity tracked
+ */
+ @NotNull
+ public Entity getEntity() {
+ return entity;
+ }
+}
diff --git a/src/main/java/io/papermc/paper/event/player/PlayerUntrackEntityEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerUntrackEntityEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..683710d53e3802ca1cb1a448886a57df6b15dd44
--- /dev/null
+++ b/src/main/java/io/papermc/paper/event/player/PlayerUntrackEntityEvent.java
@@ -0,0 +1,41 @@
+package io.papermc.paper.event.player;
+
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.Player;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.player.PlayerEvent;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Is called when a {@link Player} untracks an {@link Entity}.
+ */
+public class PlayerUntrackEntityEvent extends PlayerEvent {
+
+ private static final HandlerList handlers = new HandlerList();
+ private final Entity entity;
+
+ public PlayerUntrackEntityEvent(@NotNull Player player, @NotNull Entity entity) {
+ super(player);
+ this.entity = entity;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ /**
+ * Gets the entity that will be untracked
+ * @return the entity untracked
+ */
+ @NotNull
+ public Entity getEntity() {
+ return entity;
+ }
+}

View File

@ -18085,10 +18085,10 @@ index d5e6123622f6bbc4c3b8b91be7f9ba8e5c1c22d8..6708c2c88251f4e5f623cd785c14b2d3
return this.getHandle().getGameProfile();
}
diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java b/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java
index f1a7f306fa6091462e984e2e3c77604db6434028..23b1725679d195380a902a3b03c6b6ad3aaede19 100644
index cdf65df8a0da81eee3f159ec70dcda17712fbb21..12ebbd95cf7a8d8c926d4f2e5ba89927c26439cc 100644
--- a/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java
+++ b/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java
@@ -256,7 +256,7 @@ public class CustomChunkGenerator extends InternalChunkGenerator {
@@ -269,7 +269,7 @@ public class CustomChunkGenerator extends InternalChunkGenerator {
return ichunkaccess1;
};

View File

@ -45,10 +45,10 @@ index e24b46820394c5f220d5bf7c4e763ef95ff9e9ab..54a8548e8d3ddee049d3fed41332c94e
if (this.onGround) {
this.setDeltaMovement(this.getDeltaMovement().multiply(0.7D, -0.5D, 0.7D));
diff --git a/src/main/java/net/minecraft/world/entity/vehicle/MinecartTNT.java b/src/main/java/net/minecraft/world/entity/vehicle/MinecartTNT.java
index c10c28eb441e65c6285c25b5d4760c876909c724..ed457aeccb91c290bbd2191c9e3e52b499dc8200 100644
index 5b31c85d3bb5bcbd966d69c129e3caea14148821..beb542b2f810da9fb8379056b4d16c2b98717f28 100644
--- a/src/main/java/net/minecraft/world/entity/vehicle/MinecartTNT.java
+++ b/src/main/java/net/minecraft/world/entity/vehicle/MinecartTNT.java
@@ -46,6 +46,12 @@ public class MinecartTNT extends AbstractMinecart {
@@ -50,6 +50,12 @@ public class MinecartTNT extends AbstractMinecart {
public void tick() {
super.tick();
if (this.fuse > 0) {

View File

@ -25,10 +25,10 @@ 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
Part of this commit was authored by: Spottedleaf, sandtechnology
diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
index 8b1c39cc7f77ca36d0341fb68de1441cc61f19e4..593ea68037b467797aeeaee331a0349f7d57d800 100644
index 8b1c39cc7f77ca36d0341fb68de1441cc61f19e4..8bc8b6013ea5803e091cf3534130b72278b9c29e 100644
--- a/src/main/java/net/minecraft/network/Connection.java
+++ b/src/main/java/net/minecraft/network/Connection.java
@@ -116,6 +116,10 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
@ -160,7 +160,7 @@ index 8b1c39cc7f77ca36d0341fb68de1441cc61f19e4..593ea68037b467797aeeaee331a0349f
ChannelFuture channelfuture = this.channel.writeAndFlush(packet);
if (callbacks != null) {
@@ -275,28 +359,64 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
@@ -275,28 +359,72 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
});
}
@ -185,10 +185,6 @@ index 8b1c39cc7f77ca36d0341fb68de1441cc61f19e4..593ea68037b467797aeeaee331a0349f
}
- private void flushQueue() {
- try { // Paper - add pending task queue
- 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()) {
@ -198,19 +194,16 @@ index 8b1c39cc7f77ca36d0341fb68de1441cc61f19e4..593ea68037b467797aeeaee331a0349f
+ 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);
- }
+ synchronized (this.queue) {
+ return this.processQueue();
+ }
+ }
+ return false;
+ }
+ private boolean processQueue() {
+ try { // Paper - add pending task queue
try { // Paper - add pending task queue
- if (this.channel != null && this.channel.isOpen()) {
- Queue queue = this.queue;
+ 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
@ -223,19 +216,32 @@ index 8b1c39cc7f77ca36d0341fb68de1441cc61f19e4..593ea68037b467797aeeaee331a0349f
+ return true;
+ }
- synchronized (this.queue) {
- Connection.PacketHolder networkmanager_queuedpacket;
+ // Paper start - checking isConsumed flag and skipping packet sending
+ if (queued.isConsumed()) {
+ continue;
+ }
+ // Paper end - checking isConsumed flag and skipping packet sending
- while ((networkmanager_queuedpacket = (Connection.PacketHolder) this.queue.poll()) != null) {
- this.sendPacket(networkmanager_queuedpacket.packet, networkmanager_queuedpacket.listener);
+ Packet<?> packet = queued.packet;
+ if (!packet.isReady()) {
+ return false;
+ } else {
+ iterator.remove();
+ this.sendPacket(packet, queued.listener);
+ if (queued.tryMarkConsumed()) { // Paper - try to mark isConsumed flag for de-duplicating packet
+ this.sendPacket(packet, queued.listener);
}
-
}
}
+ return true;
} finally { // Paper start - add pending task queue
Runnable r;
while ((r = this.pendingTasks.poll()) != null) {
@@ -304,6 +424,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
@@ -304,6 +432,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
}
} // Paper end - add pending task queue
}
@ -243,7 +249,7 @@ index 8b1c39cc7f77ca36d0341fb68de1441cc61f19e4..593ea68037b467797aeeaee331a0349f
public void tick() {
this.flushQueue();
@@ -340,9 +461,22 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
@@ -340,9 +469,22 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
return this.address;
}
@ -266,7 +272,7 @@ index 8b1c39cc7f77ca36d0341fb68de1441cc61f19e4..593ea68037b467797aeeaee331a0349f
// Spigot End
if (this.channel.isOpen()) {
this.channel.close(); // We can't wait as this may be called from an event loop.
@@ -460,7 +594,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
@@ -460,7 +602,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
public void handleDisconnection() {
if (this.channel != null && !this.channel.isOpen()) {
if (this.disconnectionHandled) {
@ -275,7 +281,7 @@ index 8b1c39cc7f77ca36d0341fb68de1441cc61f19e4..593ea68037b467797aeeaee331a0349f
} else {
this.disconnectionHandled = true;
if (this.getDisconnectedReason() != null) {
@@ -468,7 +602,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
@@ -468,7 +610,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
} else if (this.getPacketListener() != null) {
this.getPacketListener().onDisconnect(Component.translatable("multiplayer.disconnect.generic"));
}
@ -284,6 +290,25 @@ index 8b1c39cc7f77ca36d0341fb68de1441cc61f19e4..593ea68037b467797aeeaee331a0349f
// Paper start - Add PlayerConnectionCloseEvent
final PacketListener packetListener = this.getPacketListener();
if (packetListener instanceof net.minecraft.server.network.ServerGamePacketListenerImpl) {
@@ -508,6 +650,18 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
@Nullable
final PacketSendListener listener;
+ // Paper start - isConsumed flag for the connection
+ private java.util.concurrent.atomic.AtomicBoolean isConsumed = new java.util.concurrent.atomic.AtomicBoolean(false);
+
+ public boolean tryMarkConsumed() {
+ return isConsumed.compareAndSet(false, true);
+ }
+
+ public boolean isConsumed() {
+ return isConsumed.get();
+ }
+ // Paper end - isConsumed flag for the connection
+
public PacketHolder(Packet<?> packet, @Nullable PacketSendListener callbacks) {
this.packet = packet;
this.listener = callbacks;
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

View File

@ -8,10 +8,10 @@ the world per tick, this attempts to reduce the impact that join floods
has on the server
diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
index bbedcdb71a326b3286805d0081e71c54a4312622..22e2e314a4bb1b22758130d4e9065f9b87b0116e 100644
index dca0c978b30962d4216dc443d7d105e54a29ae1b..3ae55dd6441b2dfdb67eb2f24ecf885bab89e7a6 100644
--- a/src/main/java/net/minecraft/network/Connection.java
+++ b/src/main/java/net/minecraft/network/Connection.java
@@ -426,8 +426,23 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
@@ -434,8 +434,23 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
}
// Paper end

View File

@ -65,10 +65,10 @@ index c3631efda9c7fa531a8a9f18fbee7b5f8655382b..9a3c1314d5a0aa20380662595359580b
}
diff --git a/src/main/java/io/papermc/paper/console/HexFormattingConverter.java b/src/main/java/io/papermc/paper/console/HexFormattingConverter.java
new file mode 100644
index 0000000000000000000000000000000000000000..b4d0b7ecd56ab952319946854168c1299cb0b1be
index 0000000000000000000000000000000000000000..b9922b07cb105618390187d98acdf89e728e1f5a
--- /dev/null
+++ b/src/main/java/io/papermc/paper/console/HexFormattingConverter.java
@@ -0,0 +1,212 @@
@@ -0,0 +1,213 @@
+package io.papermc.paper.console;
+
+import io.papermc.paper.configuration.GlobalConfiguration;
@ -117,6 +117,7 @@ index 0000000000000000000000000000000000000000..b4d0b7ecd56ab952319946854168c129
+ private static final String LOOKUP = "0123456789abcdefklmnor";
+
+ private static final String RGB_ANSI = "\u001B[38;2;%d;%d;%dm";
+ private static final String RESET_RGB_ANSI = ANSI_RESET + RGB_ANSI;
+ private static final Pattern NAMED_PATTERN = Pattern.compile(COLOR_CHAR + "[0-9a-fk-orA-FK-OR]");
+ private static final Pattern RGB_PATTERN = Pattern.compile(COLOR_CHAR + "#([0-9a-fA-F]){6}");
+
@ -145,28 +146,28 @@ index 0000000000000000000000000000000000000000..b4d0b7ecd56ab952319946854168c129
+ ANSI_RESET, // Reset §r
+ };
+ private static final String[] ANSI_ANSI_CODES = new String[]{
+ "\u001B[0;30m", // Black §0
+ "\u001B[0;34m", // Dark Blue §1
+ "\u001B[0;32m", // Dark Green §2
+ "\u001B[0;36m", // Dark Aqua §3
+ "\u001B[0;31m", // Dark Red §4
+ "\u001B[0;35m", // Dark Purple §5
+ "\u001B[0;33m", // Gold §6
+ "\u001B[0;37m", // Gray §7
+ "\u001B[0;30;1m", // Dark Gray §8
+ "\u001B[0;34;1m", // Blue §9
+ "\u001B[0;32;1m", // Green §a
+ "\u001B[0;36;1m", // Aqua §b
+ "\u001B[0;31;1m", // Red §c
+ "\u001B[0;35;1m", // Light Purple §d
+ "\u001B[0;33;1m", // Yellow §e
+ "\u001B[0;37;1m", // White §f
+ "\u001B[5m", // Obfuscated §k
+ "\u001B[1m", // Bold §l
+ "\u001B[9m", // Strikethrough §m
+ "\u001B[4m", // Underline §n
+ "\u001B[3m", // Italic §o
+ ANSI_RESET, // Reset §r
+ ANSI_RESET + "\u001B[0;30m", // Black §0
+ ANSI_RESET + "\u001B[0;34m", // Dark Blue §1
+ ANSI_RESET + "\u001B[0;32m", // Dark Green §2
+ ANSI_RESET + "\u001B[0;36m", // Dark Aqua §3
+ ANSI_RESET + "\u001B[0;31m", // Dark Red §4
+ ANSI_RESET + "\u001B[0;35m", // Dark Purple §5
+ ANSI_RESET + "\u001B[0;33m", // Gold §6
+ ANSI_RESET + "\u001B[0;37m", // Gray §7
+ ANSI_RESET + "\u001B[0;30;1m", // Dark Gray §8
+ ANSI_RESET + "\u001B[0;34;1m", // Blue §9
+ ANSI_RESET + "\u001B[0;32;1m", // Green §a
+ ANSI_RESET + "\u001B[0;36;1m", // Aqua §b
+ ANSI_RESET + "\u001B[0;31;1m", // Red §c
+ ANSI_RESET + "\u001B[0;35;1m", // Light Purple §d
+ ANSI_RESET + "\u001B[0;33;1m", // Yellow §e
+ ANSI_RESET + "\u001B[0;37;1m", // White §f
+ "\u001B[5m", // Obfuscated §k
+ "\u001B[1m", // Bold §l
+ "\u001B[9m", // Strikethrough §m
+ "\u001B[4m", // Underline §n
+ "\u001B[3m", // Italic §o
+ ANSI_RESET, // Reset §r
+ };
+
+ private final boolean ansi;
@ -218,7 +219,7 @@ index 0000000000000000000000000000000000000000..b4d0b7ecd56ab952319946854168c129
+ final int red = color >> 16 & 0xFF;
+ final int green = color >> 8 & 0xFF;
+ final int blue = color & 0xFF;
+ return String.format(RGB_ANSI, red, green, blue);
+ return String.format(RESET_RGB_ANSI, red, green, blue);
+ }
+
+ private static String stripRGBColors(final String input) {

View File

@ -122,10 +122,10 @@ index 0000000000000000000000000000000000000000..0d7e7db9e37ef0183c32b217bd944fb4
+ COMPRESSION_DISABLED
+}
diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
index de1fdb93e0e3acd58429b042629df8c00bfb65ad..13d33cd159eca63c98d7239f527c444c71519634 100644
index f76ee2131c35a9dbf7ad9d086b51c9644b0a2462..a7ab818440dc98087d877d7efdfafbf65e9ca92d 100644
--- a/src/main/java/net/minecraft/network/Connection.java
+++ b/src/main/java/net/minecraft/network/Connection.java
@@ -597,6 +597,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
@@ -605,6 +605,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
} else {
this.channel.pipeline().addBefore("encoder", "compress", new CompressionEncoder(compressionThreshold));
}
@ -133,7 +133,7 @@ index de1fdb93e0e3acd58429b042629df8c00bfb65ad..13d33cd159eca63c98d7239f527c444c
} else {
if (this.channel.pipeline().get("decompress") instanceof CompressionDecoder) {
this.channel.pipeline().remove("decompress");
@@ -605,6 +606,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
@@ -613,6 +614,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
if (this.channel.pipeline().get("compress") instanceof CompressionEncoder) {
this.channel.pipeline().remove("compress");
}

View File

@ -11,10 +11,10 @@ Tested-by: Mariell Hoversholm <proximyst@proximyst.com>
Reviewed-by: Mariell Hoversholm <proximyst@proximyst.com>
diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
index 13d33cd159eca63c98d7239f527c444c71519634..7bece5bd90d8f372ead5aef473f077a2a1ef9fa2 100644
index a7ab818440dc98087d877d7efdfafbf65e9ca92d..ea6c1439e92c24194cde4dcf6388363a8cc5d649 100644
--- a/src/main/java/net/minecraft/network/Connection.java
+++ b/src/main/java/net/minecraft/network/Connection.java
@@ -671,6 +671,11 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
@@ -691,6 +691,11 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
// Spigot Start
public SocketAddress getRawAddress()
{

View File

@ -9,7 +9,7 @@ This patch will be used to optimise out flush calls in later
patches.
diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
index 7bece5bd90d8f372ead5aef473f077a2a1ef9fa2..a71db5b49b1e6a094790d060db9f30a711581db0 100644
index ea6c1439e92c24194cde4dcf6388363a8cc5d649..40a0f68c42000757ba8b0e8bdbd4cd34cce89cfe 100644
--- a/src/main/java/net/minecraft/network/Connection.java
+++ b/src/main/java/net/minecraft/network/Connection.java
@@ -122,6 +122,39 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
@ -120,7 +120,7 @@ index 7bece5bd90d8f372ead5aef473f077a2a1ef9fa2..a71db5b49b1e6a094790d060db9f30a7
// 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();
@@ -407,16 +457,22 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
@@ -407,7 +457,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
PacketHolder queued = iterator.next(); // poll -> peek
// Fix NPE (Spigot bug caused by handleDisconnection())
@ -129,6 +129,8 @@ index 7bece5bd90d8f372ead5aef473f077a2a1ef9fa2..a71db5b49b1e6a094790d060db9f30a7
return true;
}
@@ -419,11 +469,17 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
Packet<?> packet = queued.packet;
if (!packet.isReady()) {
+ // Paper start - make only one flush call per sendPacketQueue() call
@ -139,9 +141,10 @@ index 7bece5bd90d8f372ead5aef473f077a2a1ef9fa2..a71db5b49b1e6a094790d060db9f30a7
return false;
} else {
iterator.remove();
- this.sendPacket(packet, queued.listener);
+ this.sendPacket(packet, queued.listener, (!iterator.hasNext() && (needsFlush || this.canFlush)) ? Boolean.TRUE : Boolean.FALSE); // Paper - make only one flush call per sendPacketQueue() call
+ hasWrotePacket = true; // Paper - make only one flush call per sendPacketQueue() call
if (queued.tryMarkConsumed()) { // Paper - try to mark isConsumed flag for de-duplicating packet
- this.sendPacket(packet, queued.listener);
+ this.sendPacket(packet, queued.listener, (!iterator.hasNext() && (needsFlush || this.canFlush)) ? Boolean.TRUE : Boolean.FALSE); // Paper - make only one flush call per sendPacketQueue() call
+ hasWrotePacket = true; // Paper - make only one flush call per sendPacketQueue() call
}
}
}
return true;

View File

@ -7,10 +7,10 @@ Subject: [PATCH] Detail more information in watchdog dumps
- Dump player name, player uuid, position, and world for packet handling
diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
index a71db5b49b1e6a094790d060db9f30a711581db0..489ab7c7a66969501e60fbd44c16ba4cdc180d46 100644
index 40a0f68c42000757ba8b0e8bdbd4cd34cce89cfe..31dee6fbf50db4b1fe779a8ad67ac771ac7148b7 100644
--- a/src/main/java/net/minecraft/network/Connection.java
+++ b/src/main/java/net/minecraft/network/Connection.java
@@ -505,9 +505,15 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
@@ -513,9 +513,15 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
PacketListener packetlistener = this.packetListener;
if (packetlistener instanceof TickablePacketListener) {

View File

@ -268,10 +268,10 @@ index 792883afe53d2b7989c25a81c2f9a639d5e21d20..c04379ca8a4db0f4de46ad2b3b338431
return this.threshold;
}
diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
index 08b74302e99e596a99f142856ae33ee29a9b1b77..69b8d1276045cd6742770dcedd6246bb1713fd3b 100644
index 2bc49ccf7eb2f1f3f956da365340e958dbb076a7..f1e1a4a48349c0e431b31327fdf217989db027b3 100644
--- a/src/main/java/net/minecraft/network/Connection.java
+++ b/src/main/java/net/minecraft/network/Connection.java
@@ -682,11 +682,28 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
@@ -690,11 +690,28 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
return networkmanager;
}
@ -304,7 +304,7 @@ index 08b74302e99e596a99f142856ae33ee29a9b1b77..69b8d1276045cd6742770dcedd6246bb
public boolean isEncrypted() {
return this.encrypted;
@@ -715,16 +732,17 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
@@ -723,16 +740,17 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
public void setupCompression(int compressionThreshold, boolean rejectsBadPackets) {
if (compressionThreshold >= 0) {

View File

@ -17,10 +17,10 @@ index d81ee5367205ba96eb23f885ec648a27f2cf62f8..7bb45ae3ed51975972e013aaf66acc35
if (this.isPassenger() && this.getVehicle().isRemoved()) {
this.stopRiding();
diff --git a/src/main/java/net/minecraft/world/entity/NeutralMob.java b/src/main/java/net/minecraft/world/entity/NeutralMob.java
index dedf76de5d6f46b9626ca4a98cfffe125b90dd0c..78632fd681049fbd49d0030c23ed204dbc515a44 100644
index dedf76de5d6f46b9626ca4a98cfffe125b90dd0c..7dac62b6370dae3ad6d098857c3136d5acf2bd74 100644
--- a/src/main/java/net/minecraft/world/entity/NeutralMob.java
+++ b/src/main/java/net/minecraft/world/entity/NeutralMob.java
@@ -42,18 +42,7 @@ public interface NeutralMob {
@@ -42,18 +42,11 @@ public interface NeutralMob {
UUID uuid = nbt.getUUID("AngryAt");
this.setPersistentAngerTarget(uuid);
@ -37,10 +37,14 @@ index dedf76de5d6f46b9626ca4a98cfffe125b90dd0c..78632fd681049fbd49d0030c23ed204d
-
- }
+ // Paper - Moved diff to separate method
+ // If this entity already survived its first tick, e.g. is loaded and ticked in sync, actively
+ // tick the initial persistent anger.
+ // If not, let the first tick on the baseTick call the method later down the line.
+ if (this instanceof Entity entity && !entity.firstTick) this.tickInitialPersistentAnger(world);
}
}
}
@@ -127,4 +116,26 @@ public interface NeutralMob {
@@ -127,4 +120,26 @@ public interface NeutralMob {
@Nullable
LivingEntity getTarget();

View File

@ -27,35 +27,44 @@ index 724592234e2a178a518f6ab7d09c3180780371a7..92154550b41b2e1d03deb1271b71bb3b
.flatMap(entry -> entry.getKey().stream().map(s -> Map.entry(s, entry.getValue())))
diff --git a/src/main/java/io/papermc/paper/command/subcommands/DumpListenersCommand.java b/src/main/java/io/papermc/paper/command/subcommands/DumpListenersCommand.java
new file mode 100644
index 0000000000000000000000000000000000000000..dab8d6fb489f8b3acc7c8fdaa1b5b6b83fa0eeb4
index 0000000000000000000000000000000000000000..c80485b9b0c189820687b3a8ff66a855a4b1efa7
--- /dev/null
+++ b/src/main/java/io/papermc/paper/command/subcommands/DumpListenersCommand.java
@@ -0,0 +1,120 @@
@@ -0,0 +1,171 @@
+package io.papermc.paper.command.subcommands;
+
+import com.destroystokyo.paper.util.SneakyThrow;
+import io.papermc.paper.command.PaperSubcommand;
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.reflect.Field;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+import java.util.stream.Stream;
+import net.kyori.adventure.text.Component;
+import net.minecraft.server.MinecraftServer;
+import org.bukkit.Bukkit;
+import org.bukkit.command.CommandSender;
+import org.bukkit.event.HandlerList;
+import org.bukkit.plugin.Plugin;
+import org.bukkit.plugin.RegisteredListener;
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.checkerframework.framework.qual.DefaultQualifier;
+
+import static net.kyori.adventure.text.Component.newline;
+import static net.kyori.adventure.text.Component.space;
+import static net.kyori.adventure.text.Component.text;
+import static net.kyori.adventure.text.format.NamedTextColor.GRAY;
+import static net.kyori.adventure.text.format.NamedTextColor.GREEN;
+import static net.kyori.adventure.text.format.NamedTextColor.RED;
+import static net.kyori.adventure.text.format.NamedTextColor.WHITE;
+
+@DefaultQualifier(NonNull.class)
+public final class DumpListenersCommand implements PaperSubcommand {
@ -73,13 +82,41 @@ index 0000000000000000000000000000000000000000..dab8d6fb489f8b3acc7c8fdaa1b5b6b8
+
+ @Override
+ public boolean execute(final CommandSender sender, final String subCommand, final String[] args) {
+ if (args.length >= 1 && args[0].equals("tofile")) {
+ this.dumpToFile(sender);
+ return true;
+ }
+ this.doDumpListeners(sender, args);
+ return true;
+ }
+
+ private void dumpToFile(final CommandSender sender) {
+ final File file = new File("debug/listeners-"
+ + DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss").format(LocalDateTime.now()) + ".txt");
+ try (final PrintWriter writer = new PrintWriter(file)) {
+ for (final String eventClass : eventClassNames()) {
+ final HandlerList handlers;
+ try {
+ handlers = (HandlerList) findClass(eventClass).getMethod("getHandlerList").invoke(null);
+ } catch (final ReflectiveOperationException e) {
+ continue;
+ }
+ if (handlers.getRegisteredListeners().length != 0) {
+ writer.println(eventClass);
+ }
+ for (final RegisteredListener registeredListener : handlers.getRegisteredListeners()) {
+ writer.println(" - " + registeredListener);
+ }
+ }
+ } catch (final IOException ex) {
+ throw new RuntimeException(ex);
+ }
+ sender.sendMessage(text("Dumped listeners to " + file, GREEN));
+ }
+
+ private void doDumpListeners(final CommandSender sender, final String[] args) {
+ if (args.length == 0) {
+ sender.sendMessage(text("Usage: /paper dumplisteners [className]", RED));
+ sender.sendMessage(text("Usage: /paper dumplisteners tofile|<className>", RED));
+ return;
+ }
+
@ -93,12 +130,19 @@ index 0000000000000000000000000000000000000000..dab8d6fb489f8b3acc7c8fdaa1b5b6b8
+
+ sender.sendMessage(text("Listeners for " + args[0] + ":"));
+
+ Stream.of(handlers.getRegisteredListeners())
+ .map(listener -> text(listener.getPlugin().getName(), GREEN)
+ for (final RegisteredListener listener : handlers.getRegisteredListeners()) {
+ final Component hoverText = text("Priority: " + listener.getPriority().name() + " (" + listener.getPriority().getSlot() + ")", WHITE)
+ .append(newline())
+ .append(text("Listener: " + listener.getListener()))
+ .append(newline())
+ .append(text("Executor: " + listener.getExecutor()))
+ .append(newline())
+ .append(text("Ignoring cancelled: " + listener.isIgnoringCancelled()));
+
+ sender.sendMessage(text(listener.getPlugin().getName(), GREEN)
+ .append(space())
+ .append(text("(" + listener.getListener().getClass().getName() + ")", GRAY)
+ .hoverEvent(text("Priority: " + listener.getPriority().name() + " (" + listener.getPriority().getSlot() + ")", GRAY))))
+ .forEach(sender::sendMessage);
+ .append(text("(" + listener.getListener().getClass().getName() + ")", GRAY).hoverEvent(hoverText)));
+ }
+
+ sender.sendMessage(text("Total listeners: " + handlers.getRegisteredListeners().length));
+
@ -115,16 +159,23 @@ index 0000000000000000000000000000000000000000..dab8d6fb489f8b3acc7c8fdaa1b5b6b8
+ @Override
+ public List<String> tabComplete(final CommandSender sender, final String subCommand, final String[] args) {
+ return switch (args.length) {
+ case 0 -> List.copyOf(getEventClasses());
+ case 1 -> getEventClasses().stream()
+ case 0 -> suggestions();
+ case 1 -> suggestions().stream()
+ .filter(clazz -> clazz.toLowerCase(Locale.ROOT).contains(args[0].toLowerCase(Locale.ROOT)))
+ .toList();
+ default -> Collections.emptyList();
+ };
+ }
+
+ private static List<String> suggestions() {
+ final List<String> ret = new ArrayList<>();
+ ret.add("tofile");
+ ret.addAll(eventClassNames());
+ return ret;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static Set<String> getEventClasses() {
+ private static Set<String> eventClassNames() {
+ try {
+ return (Set<String>) EVENT_TYPES_HANDLE.invokeExact();
+ } catch (final Throwable e) {

View File

@ -0,0 +1,23 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Denery <dorofeevij@gmail.com>
Date: Sun, 6 Nov 2022 02:02:46 +0300
Subject: [PATCH] Fix player kick on shutdown
Fix preemptive player kick on a server shutdown.
If you update minecraft version / upstream and something is changed in this method make sure that a server doesn't disconnect a player preemptively,
also check if all packets are ignored during the shutdown process.
See net.minecraft.network.Connection#channelRead0(ChannelHandlerContext, Packet) and net.minecraft.util.thread.BlockableEventLoop#executeIfPossible(Runnable)
diff --git a/src/main/java/net/minecraft/network/protocol/PacketUtils.java b/src/main/java/net/minecraft/network/protocol/PacketUtils.java
index 8bc0cb9ad5bb4e76d962ff54305e2c08e279a17b..27d4aa45e585842c04491839826d405d6f447f0e 100644
--- a/src/main/java/net/minecraft/network/protocol/PacketUtils.java
+++ b/src/main/java/net/minecraft/network/protocol/PacketUtils.java
@@ -41,7 +41,7 @@ public class PacketUtils {
public static <T extends PacketListener> void ensureRunningOnSameThread(Packet<T> packet, T listener, BlockableEventLoop<?> engine) throws RunningOnDifferentThreadException {
if (!engine.isSameThread()) {
- engine.executeIfPossible(() -> {
+ engine.execute(() -> { // Paper - Fix preemptive player kick on a server shutdown.
packetProcessing.push(listener); // Paper - detailed watchdog information
try { // Paper - detailed watchdog information
if (MinecraftServer.getServer().hasStopped() || (listener instanceof ServerGamePacketListenerImpl && ((ServerGamePacketListenerImpl) listener).processedDisconnect)) return; // CraftBukkit, MC-142590

View File

@ -0,0 +1,51 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Fri, 14 Jan 2022 10:20:40 -0800
Subject: [PATCH] Sync offhand slot in menus
Menus don't add slots for the offhand, so on sendAllDataToRemote calls the
offhand slot isn't sent. This is not correct because you *can* put stuff into the offhand
by pressing the offhand swap item
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index 3b122f521c166253f20d233c0fcebdede6660be5..9c9b4d7e0637348a94befce9377fdb69c1239694 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -287,6 +287,13 @@ public class ServerPlayer extends Player {
}
+ // Paper start
+ @Override
+ public void sendOffHandSlotChange() {
+ ServerPlayer.this.connection.send(new ClientboundContainerSetSlotPacket(ServerPlayer.this.inventoryMenu.containerId, ServerPlayer.this.inventoryMenu.incrementStateId(), net.minecraft.world.inventory.InventoryMenu.SHIELD_SLOT, ServerPlayer.this.inventoryMenu.getSlot(net.minecraft.world.inventory.InventoryMenu.SHIELD_SLOT).getItem().copy()));
+ }
+ // Paper end
+
@Override
public void sendSlotChange(AbstractContainerMenu handler, int slot, ItemStack stack) {
ServerPlayer.this.connection.send(new ClientboundContainerSetSlotPacket(handler.containerId, handler.incrementStateId(), slot, stack));
diff --git a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java
index 1ad44a49c1da9ede750984306960282f0df5844c..ec6c56c0564eae390de25f967d5d3d6443564ff2 100644
--- a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java
@@ -199,6 +199,7 @@ public abstract class AbstractContainerMenu {
if (this.synchronizer != null) {
this.synchronizer.sendInitialData(this, this.remoteSlots, this.remoteCarried, this.remoteDataSlots.toIntArray());
+ this.synchronizer.sendOffHandSlotChange(); // Paper - update player's offhand since the offhand slot is not added to the slots for menus but can be changed by swapping from a menu slot
}
}
diff --git a/src/main/java/net/minecraft/world/inventory/ContainerSynchronizer.java b/src/main/java/net/minecraft/world/inventory/ContainerSynchronizer.java
index ff4fa86f9408e83e505f7e27692d3423f8570c48..db6c290dcbb8f5cb502f85e154b42ac89350a460 100644
--- a/src/main/java/net/minecraft/world/inventory/ContainerSynchronizer.java
+++ b/src/main/java/net/minecraft/world/inventory/ContainerSynchronizer.java
@@ -6,6 +6,7 @@ import net.minecraft.world.item.ItemStack;
public interface ContainerSynchronizer {
void sendInitialData(AbstractContainerMenu handler, NonNullList<ItemStack> stacks, ItemStack cursorStack, int[] properties);
+ default void sendOffHandSlotChange() {} // Paper
void sendSlotChange(AbstractContainerMenu handler, int slot, ItemStack stack);
void sendCarriedChange(AbstractContainerMenu handler, ItemStack stack);

View File

@ -0,0 +1,34 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Yannick Lamprecht <yannicklamprecht@live.de>
Date: Wed, 30 Mar 2022 18:16:52 +0200
Subject: [PATCH] Player Entity Tracking Events
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 6fa47becd0f83ac4273ef3a10c314aa27b08184b..22cd5f0e40d7e3cd04793a9dda29d113428fa093 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -3796,9 +3796,21 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
EnchantmentHelper.doPostDamageEffects(attacker, target);
}
- public void startSeenByPlayer(ServerPlayer player) {}
+ // Paper start
+ public void startSeenByPlayer(ServerPlayer player) {
+ if (io.papermc.paper.event.player.PlayerTrackEntityEvent.getHandlerList().getRegisteredListeners().length > 0) {
+ new io.papermc.paper.event.player.PlayerTrackEntityEvent(player.getBukkitEntity(), this.getBukkitEntity()).callEvent();
+ }
+ }
+ // Paper end
- public void stopSeenByPlayer(ServerPlayer player) {}
+ // Paper start
+ public void stopSeenByPlayer(ServerPlayer player) {
+ if(io.papermc.paper.event.player.PlayerUntrackEntityEvent.getHandlerList().getRegisteredListeners().length > 0) {
+ new io.papermc.paper.event.player.PlayerUntrackEntityEvent(player.getBukkitEntity(), this.getBukkitEntity()).callEvent();
+ }
+ }
+ // Paper end
public float rotate(Rotation rotation) {
float f = Mth.wrapDegrees(this.getYRot());

@ -1 +1 @@
Subproject commit 9a4de0976907a81c4089cf5e8434155e77960145
Subproject commit 38866413a790619d8d8873de5b62f807947b81f6

@ -1 +1 @@
Subproject commit 300e7448f5f0466e23b97d69aa424629c816fc8e
Subproject commit f3dab3a488c6ef87abe9639d537c19b7a1029019