Paper/patches/server/0690-Add-PlayerSetSpawnEvent.patch
Spottedleaf aabf676721 Prevent unloading worlds with pending player logins
Logging into an unloaded world isn't going to end well.
This may fix the cases of people seeing errors about regionfiles
being closed, as loading chunks in an unloaded world will cause this
as the regionfile cache is closed but not cleared.
2022-08-26 22:20:27 -07:00

147 lines
9.7 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Wed, 19 May 2021 18:59:10 -0700
Subject: [PATCH] Add PlayerSetSpawnEvent
diff --git a/src/main/java/net/minecraft/server/commands/SetSpawnCommand.java b/src/main/java/net/minecraft/server/commands/SetSpawnCommand.java
index ce1c7512cc368e196ae94ee22c6a228c975b4980..1e41de9523c5fa3b9cfced798a5c35a24ec9d349 100644
--- a/src/main/java/net/minecraft/server/commands/SetSpawnCommand.java
+++ b/src/main/java/net/minecraft/server/commands/SetSpawnCommand.java
@@ -32,9 +32,21 @@ public class SetSpawnCommand {
private static int setSpawn(CommandSourceStack source, Collection<ServerPlayer> targets, BlockPos pos, float angle) {
ResourceKey<Level> resourceKey = source.getLevel().dimension();
+ final Collection<ServerPlayer> actualTargets = new java.util.ArrayList<>(); // Paper
for(ServerPlayer serverPlayer : targets) {
- serverPlayer.setRespawnPosition(resourceKey, pos, angle, true, false);
+ // Paper start - PlayerSetSpawnEvent
+ if (serverPlayer.setRespawnPosition(resourceKey, pos, angle, true, false, com.destroystokyo.paper.event.player.PlayerSetSpawnEvent.Cause.COMMAND)) {
+ actualTargets.add(serverPlayer);
+ }
+ // Paper end
}
+ // Paper start
+ if (actualTargets.isEmpty()) {
+ return 0;
+ } else {
+ targets = actualTargets;
+ }
+ // Paper end
String string = resourceKey.location().toString();
if (targets.size() == 1) {
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index 56ac440465813a7dab8d166e882e18143a50729f..80e1970f568a74a43e624188a77cfbd28cfa52dd 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -1287,7 +1287,7 @@ public class ServerPlayer extends Player {
} else if (this.bedBlocked(blockposition, enumdirection)) {
return Either.left(Player.BedSleepingProblem.OBSTRUCTED);
} else {
- this.setRespawnPosition(this.level.dimension(), blockposition, this.getYRot(), false, true);
+ this.setRespawnPosition(this.level.dimension(), blockposition, this.getYRot(), false, true, com.destroystokyo.paper.event.player.PlayerSetSpawnEvent.Cause.BED); // Paper - PlayerSetSpawnEvent
if (this.level.isDay()) {
return Either.left(Player.BedSleepingProblem.NOT_POSSIBLE_NOW);
} else {
@@ -2128,12 +2128,33 @@ public class ServerPlayer extends Player {
return this.respawnForced;
}
+ @Deprecated // Paper
public void setRespawnPosition(ResourceKey<Level> dimension, @Nullable BlockPos pos, float angle, boolean forced, boolean sendMessage) {
+ // Paper start
+ this.setRespawnPosition(dimension, pos, angle, forced, sendMessage, com.destroystokyo.paper.event.player.PlayerSetSpawnEvent.Cause.UNKNOWN);
+ }
+ public boolean setRespawnPosition(ResourceKey<Level> dimension, @Nullable BlockPos pos, float angle, boolean forced, boolean sendMessage, com.destroystokyo.paper.event.player.PlayerSetSpawnEvent.Cause cause) {
+ Location spawnLoc = null;
+ boolean willNotify = false;
if (pos != null) {
boolean flag2 = pos.equals(this.respawnPosition) && dimension.equals(this.respawnDimension);
+ spawnLoc = net.minecraft.server.MCUtil.toLocation(this.getServer().getLevel(dimension), pos);
+ spawnLoc.setYaw(angle);
+ willNotify = sendMessage && !flag2;
+ }
+ com.destroystokyo.paper.event.player.PlayerSetSpawnEvent event = new com.destroystokyo.paper.event.player.PlayerSetSpawnEvent(this.getBukkitEntity(), cause, spawnLoc, forced, willNotify, willNotify ? net.kyori.adventure.text.Component.translatable("block.minecraft.set_spawn") : null);
+ if (!event.callEvent()) {
+ return false;
+ }
+ if (event.getLocation() != null) {
+ dimension = event.getLocation().getWorld() != null ? ((CraftWorld) event.getLocation().getWorld()).getHandle().dimension() : dimension;
+ pos = net.minecraft.server.MCUtil.toBlockPosition(event.getLocation());
+ angle = (float) event.getLocation().getYaw();
+ forced = event.isForced();
+ // Paper end
- if (sendMessage && !flag2) {
- this.sendSystemMessage(Component.translatable("block.minecraft.set_spawn"));
+ if (event.willNotifyPlayer() && event.getNotification() != null) { // Paper
+ this.sendSystemMessage(PaperAdventure.asVanilla(event.getNotification())); // Paper
}
this.respawnPosition = pos;
@@ -2147,6 +2168,7 @@ public class ServerPlayer extends Player {
this.respawnForced = false;
}
+ return true; // Paper
}
public void trackChunk(ChunkPos chunkPos, Packet<?> chunkDataPacket) {
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index 0e70a431219c8c0a13cb3c9059d8a77ee2f1ca55..18772fd8a4b90ef39f208ed45355e5c3ccf06657 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -898,13 +898,13 @@ public abstract class PlayerList {
f1 = (float) Mth.wrapDegrees(Mth.atan2(vec3d1.z, vec3d1.x) * 57.2957763671875D - 90.0D);
}
- entityplayer1.setRespawnPosition(worldserver1.dimension(), blockposition, f, flag1, false);
+ entityplayer1.setRespawnPosition(worldserver1.dimension(), blockposition, f, flag1, false, com.destroystokyo.paper.event.player.PlayerSetSpawnEvent.Cause.PLAYER_RESPAWN); // Paper - PlayerSetSpawnEvent
flag2 = !flag && flag3;
isBedSpawn = true;
location = new Location(worldserver1.getWorld(), vec3d.x, vec3d.y, vec3d.z, f1, 0.0F);
} else if (blockposition != null) {
entityplayer1.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.NO_RESPAWN_BLOCK_AVAILABLE, 0.0F));
- entityplayer1.setRespawnPosition(null, null, 0f, false, false); // CraftBukkit - SPIGOT-5988: Clear respawn location when obstructed
+ entityplayer1.setRespawnPosition(null, null, 0f, false, false, com.destroystokyo.paper.event.player.PlayerSetSpawnEvent.Cause.PLAYER_RESPAWN); // CraftBukkit - SPIGOT-5988: Clear respawn location when obstructed // Paper - PlayerSetSpawnEvent
}
}
diff --git a/src/main/java/net/minecraft/world/level/block/RespawnAnchorBlock.java b/src/main/java/net/minecraft/world/level/block/RespawnAnchorBlock.java
index c3e49a781f838e6a46cb89744f3f1846de182275..c2f3d3a09327e7cb7d3167609eb3ce68eadf6443 100644
--- a/src/main/java/net/minecraft/world/level/block/RespawnAnchorBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/RespawnAnchorBlock.java
@@ -72,9 +72,14 @@ public class RespawnAnchorBlock extends Block {
if (!world.isClientSide) {
ServerPlayer serverPlayer = (ServerPlayer)player;
if (serverPlayer.getRespawnDimension() != world.dimension() || !pos.equals(serverPlayer.getRespawnPosition())) {
- serverPlayer.setRespawnPosition(world.dimension(), pos, 0.0F, false, true);
+ if (serverPlayer.setRespawnPosition(world.dimension(), pos, 0.0F, false, true, com.destroystokyo.paper.event.player.PlayerSetSpawnEvent.Cause.RESPAWN_ANCHOR)) { // Paper - PlayerSetSpawnEvent
world.playSound((Player)null, (double)pos.getX() + 0.5D, (double)pos.getY() + 0.5D, (double)pos.getZ() + 0.5D, SoundEvents.RESPAWN_ANCHOR_SET_SPAWN, SoundSource.BLOCKS, 1.0F, 1.0F);
return InteractionResult.SUCCESS;
+ // Paper start - handle failed set spawn
+ } else {
+ return InteractionResult.FAIL;
+ }
+ // Paper end
}
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 4750ac09f2abfb712b042028a95d23121ffc049f..d309c994ffd72952cf9a8f2f4cc21231417bb9ed 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -1216,9 +1216,9 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
@Override
public void setBedSpawnLocation(Location location, boolean override) {
if (location == null) {
- this.getHandle().setRespawnPosition(null, null, 0.0F, override, false);
+ this.getHandle().setRespawnPosition(null, null, 0.0F, override, false, com.destroystokyo.paper.event.player.PlayerSetSpawnEvent.Cause.PLUGIN); // Paper - PlayerSetSpawnEvent
} else {
- this.getHandle().setRespawnPosition(((CraftWorld) location.getWorld()).getHandle().dimension(), new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()), location.getYaw(), override, false);
+ this.getHandle().setRespawnPosition(((CraftWorld) location.getWorld()).getHandle().dimension(), new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()), location.getYaw(), override, false, com.destroystokyo.paper.event.player.PlayerSetSpawnEvent.Cause.PLUGIN); // Paper - PlayerSetSpawnEvent
}
}