From 8cf7eab2348b0c17609f53ee8df7e7d06107180c Mon Sep 17 00:00:00 2001 From: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com> Date: Tue, 24 Dec 2024 21:25:39 +0100 Subject: [PATCH] Parity for respawn events --- .../event/player/PlayerPostRespawnEvent.java | 30 +++---- .../event/player/AbstractRespawnEvent.java | 82 +++++++++++++++++ .../event/player/PlayerRespawnEvent.java | 87 +++---------------- .../0017-Moonrise-optimisation-patches.patch | 8 +- ...-Incremental-chunk-and-player-saving.patch | 6 +- .../server/level/ServerPlayer.java.patch | 9 +- .../server/players/PlayerList.java.patch | 21 +++-- 7 files changed, 128 insertions(+), 115 deletions(-) create mode 100644 paper-api/src/main/java/io/papermc/paper/event/player/AbstractRespawnEvent.java diff --git a/paper-api/src/main/java/com/destroystokyo/paper/event/player/PlayerPostRespawnEvent.java b/paper-api/src/main/java/com/destroystokyo/paper/event/player/PlayerPostRespawnEvent.java index e82446ec3d..8f0db9a6e9 100644 --- a/paper-api/src/main/java/com/destroystokyo/paper/event/player/PlayerPostRespawnEvent.java +++ b/paper-api/src/main/java/com/destroystokyo/paper/event/player/PlayerPostRespawnEvent.java @@ -1,9 +1,10 @@ package com.destroystokyo.paper.event.player; +import io.papermc.paper.event.player.AbstractRespawnEvent; import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.event.HandlerList; -import org.bukkit.event.player.PlayerEvent; +import org.bukkit.event.player.PlayerRespawnEvent; import org.jetbrains.annotations.ApiStatus; import org.jspecify.annotations.NullMarked; @@ -11,36 +12,25 @@ import org.jspecify.annotations.NullMarked; * Fired after a player has respawned */ @NullMarked -public class PlayerPostRespawnEvent extends PlayerEvent { +public class PlayerPostRespawnEvent extends AbstractRespawnEvent { private static final HandlerList HANDLER_LIST = new HandlerList(); - private final Location respawnedLocation; - private final boolean isBedSpawn; - @ApiStatus.Internal - public PlayerPostRespawnEvent(final Player respawnPlayer, final Location respawnedLocation, final boolean isBedSpawn) { - super(respawnPlayer); - this.respawnedLocation = respawnedLocation; - this.isBedSpawn = isBedSpawn; + public PlayerPostRespawnEvent(final Player respawnPlayer, final Location respawnLocation, final boolean isBedSpawn, final boolean isAnchorSpawn, + final PlayerRespawnEvent.RespawnReason respawnReason) { + super(respawnPlayer, respawnLocation, isBedSpawn, isAnchorSpawn, respawnReason); } /** - * Returns the location of the respawned player + * Returns the location of the respawned player. * * @return location of the respawned player + * @see #getRespawnLocation() */ + @ApiStatus.Obsolete public Location getRespawnedLocation() { - return this.respawnedLocation.clone(); - } - - /** - * Checks if the player respawned to their bed - * - * @return whether the player respawned to their bed - */ - public boolean isBedSpawn() { - return this.isBedSpawn; + return super.getRespawnLocation(); } @Override diff --git a/paper-api/src/main/java/io/papermc/paper/event/player/AbstractRespawnEvent.java b/paper-api/src/main/java/io/papermc/paper/event/player/AbstractRespawnEvent.java new file mode 100644 index 0000000000..6f84f2f17c --- /dev/null +++ b/paper-api/src/main/java/io/papermc/paper/event/player/AbstractRespawnEvent.java @@ -0,0 +1,82 @@ +package io.papermc.paper.event.player; + +import com.google.common.collect.ImmutableSet; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.player.PlayerEvent; +import org.bukkit.event.player.PlayerRespawnEvent; +import org.jspecify.annotations.NullMarked; +import java.util.Set; + +@NullMarked +public abstract class AbstractRespawnEvent extends PlayerEvent { + + protected Location respawnLocation; + private final boolean isBedSpawn; + private final boolean isAnchorSpawn; + private final PlayerRespawnEvent.RespawnReason respawnReason; + private final Set respawnFlags; + + protected AbstractRespawnEvent( + final Player respawnPlayer, final Location respawnLocation, final boolean isBedSpawn, + final boolean isAnchorSpawn, final PlayerRespawnEvent.RespawnReason respawnReason + ) { + super(respawnPlayer); + this.respawnLocation = respawnLocation; + this.isBedSpawn = isBedSpawn; + this.isAnchorSpawn = isAnchorSpawn; + this.respawnReason = respawnReason; + ImmutableSet.Builder builder = ImmutableSet.builder(); + if (respawnReason == PlayerRespawnEvent.RespawnReason.END_PORTAL) builder.add(PlayerRespawnEvent.RespawnFlag.END_PORTAL); + if (this.isBedSpawn) builder.add(PlayerRespawnEvent.RespawnFlag.BED_SPAWN); + if (this.isAnchorSpawn) builder.add(PlayerRespawnEvent.RespawnFlag.ANCHOR_SPAWN); + this.respawnFlags = builder.build(); + } + + /** + * Gets the current respawn location. + * + * @return the current respawn location + */ + public Location getRespawnLocation() { + return this.respawnLocation.clone(); + } + + /** + * Gets whether the respawn location is the player's bed. + * + * @return {@code true} if the respawn location is the player's bed + */ + public boolean isBedSpawn() { + return this.isBedSpawn; + } + + /** + * Gets whether the respawn location is the player's respawn anchor. + * + * @return {@code true} if the respawn location is the player's respawn anchor + */ + public boolean isAnchorSpawn() { + return this.isAnchorSpawn; + } + + /** + * Gets the reason this respawn event was called. + * + * @return the reason the event was called + */ + public PlayerRespawnEvent.RespawnReason getRespawnReason() { + return this.respawnReason; + } + + /** + * Gets the set of flags that apply to this respawn. + * + * @return an immutable set of the flags that apply to this respawn + * @deprecated in favour of {@link #getRespawnReason()}/{@link #isBedSpawn}/{@link #isAnchorSpawn()} + */ + @Deprecated + public Set getRespawnFlags() { + return this.respawnFlags; + } +} diff --git a/paper-api/src/main/java/org/bukkit/event/player/PlayerRespawnEvent.java b/paper-api/src/main/java/org/bukkit/event/player/PlayerRespawnEvent.java index d1dd5cf0ad..bd51bf67ea 100644 --- a/paper-api/src/main/java/org/bukkit/event/player/PlayerRespawnEvent.java +++ b/paper-api/src/main/java/org/bukkit/event/player/PlayerRespawnEvent.java @@ -1,9 +1,11 @@ package org.bukkit.event.player; import com.google.common.base.Preconditions; +import io.papermc.paper.event.player.AbstractRespawnEvent; import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.event.HandlerList; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; /** @@ -12,13 +14,8 @@ import org.jetbrains.annotations.NotNull; * If changing player state, see {@link com.destroystokyo.paper.event.player.PlayerPostRespawnEvent} * because the player is "reset" between this event and that event and some changes won't persist. */ -public class PlayerRespawnEvent extends PlayerEvent { +public class PlayerRespawnEvent extends AbstractRespawnEvent { private static final HandlerList handlers = new HandlerList(); - private Location respawnLocation; - private final boolean isBedSpawn; - private final boolean isAnchorSpawn; - private final RespawnReason respawnReason; - private final java.util.Set respawnFlags; // Paper @Deprecated(since = "1.16.1") public PlayerRespawnEvent(@NotNull final Player respawnPlayer, @NotNull final Location respawnLocation, final boolean isBedSpawn) { @@ -27,41 +24,16 @@ public class PlayerRespawnEvent extends PlayerEvent { @Deprecated(since = "1.19.4") public PlayerRespawnEvent(@NotNull final Player respawnPlayer, @NotNull final Location respawnLocation, final boolean isBedSpawn, final boolean isAnchorSpawn) { - this(respawnPlayer, respawnLocation, isBedSpawn, false, RespawnReason.PLUGIN); + this(respawnPlayer, respawnLocation, isBedSpawn, isAnchorSpawn, RespawnReason.PLUGIN); } - @Deprecated // Paper + @ApiStatus.Internal public PlayerRespawnEvent(@NotNull final Player respawnPlayer, @NotNull final Location respawnLocation, final boolean isBedSpawn, final boolean isAnchorSpawn, @NotNull final RespawnReason respawnReason) { - // Paper start - this(respawnPlayer, respawnLocation, isBedSpawn, isAnchorSpawn, respawnReason, com.google.common.collect.ImmutableSet.builder()); - } - - public PlayerRespawnEvent(@NotNull final Player respawnPlayer, @NotNull final Location respawnLocation, final boolean isBedSpawn, final boolean isAnchorSpawn, @NotNull final RespawnReason respawnReason, @NotNull final com.google.common.collect.ImmutableSet.Builder respawnFlags) { - // Paper end - super(respawnPlayer); - this.respawnLocation = respawnLocation; - this.isBedSpawn = isBedSpawn; - this.isAnchorSpawn = isAnchorSpawn; - this.respawnReason = respawnReason; - // Paper start - if (this.isBedSpawn) { respawnFlags.add(RespawnFlag.BED_SPAWN); } - if (this.isAnchorSpawn) { respawnFlags.add(RespawnFlag.ANCHOR_SPAWN); } - this.respawnFlags = respawnFlags.build(); - // Paper end + super(respawnPlayer, respawnLocation, isBedSpawn, isAnchorSpawn, respawnReason); } /** - * Gets the current respawn location - * - * @return Location current respawn location - */ - @NotNull - public Location getRespawnLocation() { - return this.respawnLocation; - } - - /** - * Sets the new respawn location + * Sets the new respawn location. * * @param respawnLocation new location for the respawn */ @@ -72,34 +44,6 @@ public class PlayerRespawnEvent extends PlayerEvent { this.respawnLocation = respawnLocation.clone(); } - /** - * Gets whether the respawn location is the player's bed. - * - * @return true if the respawn location is the player's bed. - */ - public boolean isBedSpawn() { - return this.isBedSpawn; - } - - /** - * Gets whether the respawn location is the player's respawn anchor. - * - * @return true if the respawn location is the player's respawn anchor. - */ - public boolean isAnchorSpawn() { - return isAnchorSpawn; - } - - /** - * Gets the reason this respawn event was called. - * - * @return the reason the event was called. - */ - @NotNull - public RespawnReason getRespawnReason() { - return respawnReason; - } - @NotNull @Override public HandlerList getHandlers() { @@ -127,20 +71,14 @@ public class PlayerRespawnEvent extends PlayerEvent { /** * When a plugin respawns the player. */ - PLUGIN; + PLUGIN } - // Paper start /** - * Get the set of flags that apply to this respawn. - * - * @return an immutable set of the flags that apply to this respawn + * @deprecated in favor of {@link RespawnReason} or + * {@link #isBedSpawn()}/{@link #isAnchorSpawn()} */ - @NotNull - public java.util.Set getRespawnFlags() { - return respawnFlags; - } - + @Deprecated public enum RespawnFlag { /** * Will use the bed spawn location @@ -153,7 +91,6 @@ public class PlayerRespawnEvent extends PlayerEvent { /** * Is caused by going to the end portal in the end. */ - END_PORTAL, + END_PORTAL } - // Paper end } diff --git a/paper-server/patches/features/0017-Moonrise-optimisation-patches.patch b/paper-server/patches/features/0017-Moonrise-optimisation-patches.patch index 337302aaa2..c0a7ed0a53 100644 --- a/paper-server/patches/features/0017-Moonrise-optimisation-patches.patch +++ b/paper-server/patches/features/0017-Moonrise-optimisation-patches.patch @@ -27496,7 +27496,7 @@ index 192977dd661ee795ada13db895db770293e9b402..95a4e37a3c93f9b3c56c7a7376ed521c } diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index ff5889f8fed0707a6654d9d21862e32e2ebc866d..e61fe83479f095e8addbd3e8f1d5179c998ae1eb 100644 +index 9041bbcde78e6cbcaed17dec0781c8941f037591..7ad7c7e3bb40d4f2b28f4f5c3132b13f38490e49 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java @@ -178,7 +178,7 @@ import net.minecraft.world.scores.Team; @@ -27976,10 +27976,10 @@ index 4eb040006f5d41b47e5ac9df5d9f19c4315d6343..7fa41dea184b01891f45d8e404bc1cba this.generatingStep = generatingStep; this.cache = cache; diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java -index ff0315cffdb282fdc0a1ffd15e2954caa76835c9..5e94dd9e26aa4fd6545dbaae2ae0cb51cb6f13e0 100644 +index ce487e2c4bcc0bab166ebfd203722ab120ec1cbc..0be9d38dda84d0a1cd6bd6b2748f978fa1286da6 100644 --- a/net/minecraft/server/players/PlayerList.java +++ b/net/minecraft/server/players/PlayerList.java -@@ -1312,7 +1312,7 @@ public abstract class PlayerList { +@@ -1321,7 +1321,7 @@ public abstract class PlayerList { public void setViewDistance(int viewDistance) { this.viewDistance = viewDistance; @@ -27988,7 +27988,7 @@ index ff0315cffdb282fdc0a1ffd15e2954caa76835c9..5e94dd9e26aa4fd6545dbaae2ae0cb51 for (ServerLevel serverLevel : this.server.getAllLevels()) { if (serverLevel != null) { -@@ -1323,7 +1323,7 @@ public abstract class PlayerList { +@@ -1332,7 +1332,7 @@ public abstract class PlayerList { public void setSimulationDistance(int simulationDistance) { this.simulationDistance = simulationDistance; diff --git a/paper-server/patches/features/0025-Incremental-chunk-and-player-saving.patch b/paper-server/patches/features/0025-Incremental-chunk-and-player-saving.patch index 4ac088fbda..0e84318d31 100644 --- a/paper-server/patches/features/0025-Incremental-chunk-and-player-saving.patch +++ b/paper-server/patches/features/0025-Incremental-chunk-and-player-saving.patch @@ -83,7 +83,7 @@ index 46dfaed12c998c219a20c711a06531aed2c68012..ebeeb63c3dca505a3ce8b88feaa5d2ca // Paper start - add close param this.save(progress, flush, skipSave, false); diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index e61fe83479f095e8addbd3e8f1d5179c998ae1eb..0a7e5106a1d39150326e7c323030df5d32ecef1e 100644 +index 7ad7c7e3bb40d4f2b28f4f5c3132b13f38490e49..81ebb33cb93c297d48bf073f335613bfaa513524 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java @@ -180,6 +180,7 @@ import org.slf4j.Logger; @@ -95,7 +95,7 @@ index e61fe83479f095e8addbd3e8f1d5179c998ae1eb..0a7e5106a1d39150326e7c323030df5d private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_Y = 10; private static final int FLY_STAT_RECORDING_SPEED = 25; diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java -index 5e94dd9e26aa4fd6545dbaae2ae0cb51cb6f13e0..03feaf0adb8ee87e33744a4615dc2507a02f92d7 100644 +index 0be9d38dda84d0a1cd6bd6b2748f978fa1286da6..aeca484f95516d3d994ae6aee3c6a381a2a7bec5 100644 --- a/net/minecraft/server/players/PlayerList.java +++ b/net/minecraft/server/players/PlayerList.java @@ -482,6 +482,7 @@ public abstract class PlayerList { @@ -106,7 +106,7 @@ index 5e94dd9e26aa4fd6545dbaae2ae0cb51cb6f13e0..03feaf0adb8ee87e33744a4615dc2507 this.playerIo.save(player); ServerStatsCounter serverStatsCounter = player.getStats(); // CraftBukkit if (serverStatsCounter != null) { -@@ -1064,9 +1065,23 @@ public abstract class PlayerList { +@@ -1073,9 +1074,23 @@ public abstract class PlayerList { } public void saveAll() { diff --git a/paper-server/patches/sources/net/minecraft/server/level/ServerPlayer.java.patch b/paper-server/patches/sources/net/minecraft/server/level/ServerPlayer.java.patch index c32e052b23..f6041420c1 100644 --- a/paper-server/patches/sources/net/minecraft/server/level/ServerPlayer.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/level/ServerPlayer.java.patch @@ -511,7 +511,7 @@ BlockPos respawnPosition = this.getRespawnPosition(); float respawnAngle = this.getRespawnAngle(); boolean isRespawnForced = this.isRespawnForced(); -@@ -973,13 +_,66 @@ +@@ -973,13 +_,61 @@ Optional optional = findRespawnAndUseSpawnBlock(level, respawnPosition, respawnAngle, isRespawnForced, useCharge); if (optional.isPresent()) { ServerPlayer.RespawnPosAngle respawnPosAngle = optional.get(); @@ -544,17 +544,12 @@ + ); + + // Paper start - respawn flags -+ com.google.common.collect.ImmutableSet.Builder builder = com.google.common.collect.ImmutableSet.builder(); -+ if (respawnReason == org.bukkit.event.player.PlayerRespawnEvent.RespawnReason.END_PORTAL) { -+ builder.add(org.bukkit.event.player.PlayerRespawnEvent.RespawnFlag.END_PORTAL); -+ } + org.bukkit.event.player.PlayerRespawnEvent respawnEvent = new org.bukkit.event.player.PlayerRespawnEvent( + respawnPlayer, + location, + isBedSpawn, + isAnchorSpawn, -+ respawnReason, -+ builder ++ respawnReason + ); + // Paper end - respawn flags + this.level().getCraftServer().getPluginManager().callEvent(respawnEvent); diff --git a/paper-server/patches/sources/net/minecraft/server/players/PlayerList.java.patch b/paper-server/patches/sources/net/minecraft/server/players/PlayerList.java.patch index e9cb8b46e9..116d9532e5 100644 --- a/paper-server/patches/sources/net/minecraft/server/players/PlayerList.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/players/PlayerList.java.patch @@ -527,7 +527,7 @@ IpBanListEntry ipBanListEntry = this.ipBans.get(socketAddress); MutableComponent mutableComponent = Component.translatable("multiplayer.disconnect.banned_ip.reason", ipBanListEntry.getReason()); if (ipBanListEntry.getExpires() != null) { -@@ -378,69 +_,129 @@ +@@ -378,69 +_,130 @@ ); } @@ -617,7 +617,7 @@ + public ServerPlayer respawn(ServerPlayer player, boolean keepInventory, Entity.RemovalReason reason, org.bukkit.event.player.PlayerRespawnEvent.RespawnReason eventReason) { + return this.respawn(player, keepInventory, reason, eventReason, null); + } -+ public ServerPlayer respawn(ServerPlayer player, boolean keepInventory, Entity.RemovalReason reason, org.bukkit.event.player.PlayerRespawnEvent.RespawnReason eventReason, org.bukkit.Location location) { ++ public ServerPlayer respawn(ServerPlayer player, boolean keepInventory, Entity.RemovalReason reason, org.bukkit.event.player.PlayerRespawnEvent.RespawnReason eventReason, @Nullable org.bukkit.Location location) { + player.stopRiding(); // CraftBukkit this.players.remove(player); + this.playersByName.remove(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT)); // Spigot @@ -651,6 +651,7 @@ + // Paper start - Add PlayerPostRespawnEvent + boolean isBedSpawn = false; + boolean isRespawn = false; ++ boolean isAnchorSpawn = false; + // Paper end - Add PlayerPostRespawnEvent + + // CraftBukkit start - fire PlayerRespawnEvent @@ -716,14 +717,18 @@ serverPlayer.setHealth(serverPlayer.getHealth()); BlockPos respawnPosition = serverPlayer.getRespawnPosition(); ServerLevel level1 = this.server.getLevel(serverPlayer.getRespawnDimension()); -@@ -472,7 +_,40 @@ +@@ -472,7 +_,48 @@ ) ); } - } + // Paper start - Add PlayerPostRespawnEvent -+ if (blockState.is(net.minecraft.tags.BlockTags.BEDS) && !teleportTransition.missingRespawnBlock()) { -+ isBedSpawn = true; ++ if (!teleportTransition.missingRespawnBlock()) { ++ if (blockState.is(net.minecraft.tags.BlockTags.BEDS)) { ++ isBedSpawn = true; ++ } else if (blockState.is(Blocks.RESPAWN_ANCHOR)) { ++ isAnchorSpawn = true; ++ } + } + // Paper end - Add PlayerPostRespawnEvent + } @@ -750,7 +755,11 @@ + + // Paper start - Add PlayerPostRespawnEvent + if (isRespawn) { -+ cserver.getPluginManager().callEvent(new com.destroystokyo.paper.event.player.PlayerPostRespawnEvent(player.getBukkitEntity(), location, isBedSpawn)); ++ new com.destroystokyo.paper.event.player.PlayerPostRespawnEvent( ++ player.getBukkitEntity(), location, ++ isBedSpawn, isAnchorSpawn, ++ eventReason ++ ).callEvent(); + } + // Paper end - Add PlayerPostRespawnEvent +