From 0e4e270396438d16ed21862f001fd098b7b4c119 Mon Sep 17 00:00:00 2001 From: Jake Potrebic Date: Wed, 19 May 2021 18:59:10 -0700 Subject: [PATCH] Add PlayerSetSpawnEvent --- .../commands/SetSpawnCommand.java.patch | 35 ++++- .../server/level/ServerPlayer.java.patch | 143 +++++++++--------- .../server/players/PlayerList.java.patch | 2 +- .../level/block/RespawnAnchorBlock.java.patch | 15 +- .../craftbukkit/entity/CraftPlayer.java | 4 +- 5 files changed, 122 insertions(+), 77 deletions(-) diff --git a/paper-server/patches/sources/net/minecraft/server/commands/SetSpawnCommand.java.patch b/paper-server/patches/sources/net/minecraft/server/commands/SetSpawnCommand.java.patch index 625935787c..f4a5c32f80 100644 --- a/paper-server/patches/sources/net/minecraft/server/commands/SetSpawnCommand.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/commands/SetSpawnCommand.java.patch @@ -1,11 +1,42 @@ --- a/net/minecraft/server/commands/SetSpawnCommand.java +++ b/net/minecraft/server/commands/SetSpawnCommand.java -@@ -41,7 +41,7 @@ +@@ -38,24 +38,34 @@ + ResourceKey resourcekey = source.getLevel().dimension(); + Iterator iterator = targets.iterator(); + ++ final Collection actualTargets = new java.util.ArrayList<>(); // Paper - Add PlayerSetSpawnEvent while (iterator.hasNext()) { ServerPlayer entityplayer = (ServerPlayer) iterator.next(); - entityplayer.setRespawnPosition(resourcekey, pos, angle, true, false); -+ entityplayer.setRespawnPosition(resourcekey, pos, angle, true, false, org.bukkit.event.player.PlayerSpawnChangeEvent.Cause.COMMAND); // CraftBukkit ++ // Paper start - Add PlayerSetSpawnEvent ++ if (entityplayer.setRespawnPosition(resourcekey, pos, angle, true, false, com.destroystokyo.paper.event.player.PlayerSetSpawnEvent.Cause.COMMAND)) { ++ actualTargets.add(entityplayer); ++ } ++ // Paper end - Add PlayerSetSpawnEvent } ++ // Paper start - Add PlayerSetSpawnEvent ++ if (actualTargets.isEmpty()) { ++ return 0; ++ } ++ // Paper end - Add PlayerSetSpawnEvent String s = resourcekey.location().toString(); + +- if (targets.size() == 1) { ++ if (actualTargets.size() == 1) { // Paper - Add PlayerSetSpawnEvent + source.sendSuccess(() -> { +- return Component.translatable("commands.spawnpoint.success.single", pos.getX(), pos.getY(), pos.getZ(), angle, s, ((ServerPlayer) targets.iterator().next()).getDisplayName()); ++ return Component.translatable("commands.spawnpoint.success.single", pos.getX(), pos.getY(), pos.getZ(), angle, s, ((ServerPlayer) actualTargets.iterator().next()).getDisplayName()); // Paper - Add PlayerSetSpawnEvent + }, true); + } else { + source.sendSuccess(() -> { +- return Component.translatable("commands.spawnpoint.success.multiple", pos.getX(), pos.getY(), pos.getZ(), angle, s, targets.size()); ++ return Component.translatable("commands.spawnpoint.success.multiple", pos.getX(), pos.getY(), pos.getZ(), angle, s, actualTargets.size()); // Paper - Add PlayerSetSpawnEvent + }, true); + } + +- return targets.size(); ++ return actualTargets.size(); // Paper - Add PlayerSetSpawnEvent + } + } 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 673d4b2c1e..e47e293e3e 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 @@ -187,8 +187,8 @@ + this.adventure$displayName = net.kyori.adventure.text.Component.text(this.getScoreboardName()); // Paper + this.bukkitPickUpLoot = true; + this.maxHealthCache = this.getMaxHealth(); - } - ++ } ++ + // Use method to resend items in hands in case of client desync, because the item use got cancelled. + // For example, when cancelling the leash event + public void resendItemInHands() { @@ -234,9 +234,9 @@ + } + + return blockposition; -+ } + } + // CraftBukkit end -+ + @Override public BlockPos adjustSpawnLocation(ServerLevel world, BlockPos basePos) { AABB axisalignedbb = this.getDimensions(Pose.STANDING).makeBoundingBox(Vec3.ZERO); @@ -526,8 +526,8 @@ + this.level().getCraftServer().getScoreboardManager().forAllObjectives(criterion, this, (scoreaccess) -> { scoreaccess.set(score); }); -+ } -+ + } + + // Paper start - PlayerDeathEvent#getItemsToKeep + private static void processKeep(org.bukkit.event.entity.PlayerDeathEvent event, NonNullList inv) { + List itemsToKeep = event.getItemsToKeep(); @@ -565,9 +565,9 @@ + inv.set(i, ItemStack.EMPTY); + } + } - } ++ } + // Paper end - PlayerDeathEvent#getItemsToKeep - ++ @Override public void die(DamageSource damageSource) { - this.gameEvent(GameEvent.ENTITY_DIE); @@ -912,7 +912,7 @@ this.connection.resetPosition(); worldserver.addDuringTeleport(this); gameprofilerfiller.pop(); -@@ -1215,10 +1604,33 @@ +@@ -1215,12 +1604,35 @@ this.lastSentExp = -1; this.lastSentHealth = -1.0F; this.lastSentFood = -1; @@ -928,24 +928,26 @@ + // Paper end - Reset shield blocking on dimension change return this; } -+ } -+ } -+ + } + } + + // CraftBukkit start -+ @Override + @Override + public CraftPortalEvent callPortalEvent(Entity entity, Location exit, TeleportCause cause, int searchRadius, int creationRadius) { + Location enter = this.getBukkitEntity().getLocation(); + PlayerPortalEvent event = new PlayerPortalEvent(this.getBukkitEntity(), enter, exit, cause, searchRadius, true, creationRadius); + Bukkit.getServer().getPluginManager().callEvent(event); + if (event.isCancelled() || event.getTo() == null || event.getTo().getWorld() == null) { + return null; - } ++ } + return new CraftPortalEvent(event); - } ++ } + // CraftBukkit end - - @Override ++ ++ @Override public void forceSetRotation(float yaw, float pitch) { + this.connection.send(new ClientboundPlayerRotationPacket(yaw, pitch)); + } @@ -1228,13 +1640,21 @@ public void triggerDimensionChangeTriggers(ServerLevel origin) { ResourceKey resourcekey = origin.dimension(); @@ -996,7 +998,7 @@ + return Either.left(net.minecraft.world.entity.player.Player.BedSleepingProblem.OBSTRUCTED); } else { - this.setRespawnPosition(this.level().dimension(), pos, this.getYRot(), false, true); -+ this.setRespawnPosition(this.level().dimension(), blockposition, this.getYRot(), false, true, PlayerSpawnChangeEvent.Cause.BED); // CraftBukkit ++ this.setRespawnPosition(this.level().dimension(), blockposition, this.getYRot(), false, true, com.destroystokyo.paper.event.player.PlayerSetSpawnEvent.Cause.BED); // Paper - Add PlayerSetSpawnEvent if (this.level().isDay()) { - return Either.left(Player.BedSleepingProblem.NOT_POSSIBLE_NOW); + return Either.left(net.minecraft.world.entity.player.Player.BedSleepingProblem.NOT_POSSIBLE_NOW); @@ -1485,58 +1487,62 @@ } @Override -@@ -2046,17 +2618,43 @@ +@@ -2045,12 +2617,44 @@ + this.setRespawnPosition(player.getRespawnDimension(), player.getRespawnPosition(), player.getRespawnAngle(), player.isRespawnForced(), false); } ++ @Deprecated // Paper - Add PlayerSetSpawnEvent public void setRespawnPosition(ResourceKey dimension, @Nullable BlockPos pos, float angle, boolean forced, boolean sendMessage) { -- if (pos != null) { -- boolean flag2 = pos.equals(this.respawnPosition) && dimension.equals(this.respawnDimension); -+ // CraftBukkit start -+ this.setRespawnPosition(dimension, pos, angle, forced, sendMessage, PlayerSpawnChangeEvent.Cause.UNKNOWN); ++ // Paper start - Add PlayerSetSpawnEvent ++ this.setRespawnPosition(dimension, pos, angle, forced, sendMessage, com.destroystokyo.paper.event.player.PlayerSetSpawnEvent.Cause.UNKNOWN); + } ++ @Deprecated ++ public boolean setRespawnPosition(ResourceKey dimension, @Nullable BlockPos pos, float angle, boolean forced, boolean sendMessage, PlayerSpawnChangeEvent.Cause cause) { ++ return this.setRespawnPosition(dimension, pos, angle, forced, sendMessage, cause == PlayerSpawnChangeEvent.Cause.RESET ? ++ com.destroystokyo.paper.event.player.PlayerSetSpawnEvent.Cause.PLAYER_RESPAWN : com.destroystokyo.paper.event.player.PlayerSetSpawnEvent.Cause.valueOf(cause.name())); ++ } ++ public boolean setRespawnPosition(ResourceKey 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 = io.papermc.paper.util.MCUtil.toLocation(this.getServer().getLevel(dimension), pos); ++ spawnLoc.setYaw(angle); ++ willNotify = sendMessage && !flag2; ++ } - if (sendMessage && !flag2) { -+ public void setRespawnPosition(ResourceKey resourcekey, @Nullable BlockPos blockposition, float f, boolean flag, boolean flag1, PlayerSpawnChangeEvent.Cause cause) { -+ ServerLevel newWorld = this.server.getLevel(resourcekey); -+ Location newSpawn = (blockposition != null) ? CraftLocation.toBukkit(blockposition, newWorld.getWorld(), f, 0) : null; +- this.sendSystemMessage(Component.translatable("block.minecraft.set_spawn")); ++ PlayerSpawnChangeEvent dumbEvent = new PlayerSpawnChangeEvent(this.getBukkitEntity(), spawnLoc, forced, ++ cause == com.destroystokyo.paper.event.player.PlayerSetSpawnEvent.Cause.PLAYER_RESPAWN ? PlayerSpawnChangeEvent.Cause.RESET : PlayerSpawnChangeEvent.Cause.valueOf(cause.name())); ++ dumbEvent.callEvent(); + -+ PlayerSpawnChangeEvent event = new PlayerSpawnChangeEvent(this.getBukkitEntity(), newSpawn, flag, cause); -+ Bukkit.getServer().getPluginManager().callEvent(event); -+ if (event.isCancelled()) { -+ return; ++ com.destroystokyo.paper.event.player.PlayerSetSpawnEvent event = new com.destroystokyo.paper.event.player.PlayerSetSpawnEvent(this.getBukkitEntity(), cause, dumbEvent.getNewSpawn(), dumbEvent.isForced(), willNotify, willNotify ? net.kyori.adventure.text.Component.translatable("block.minecraft.set_spawn") : null); ++ event.setCancelled(dumbEvent.isCancelled()); ++ if (!event.callEvent()) { ++ return false; + } -+ newSpawn = event.getNewSpawn(); -+ flag = event.isForced(); ++ if (event.getLocation() != null) { ++ dimension = event.getLocation().getWorld() != null ? ((CraftWorld) event.getLocation().getWorld()).getHandle().dimension() : dimension; ++ pos = io.papermc.paper.util.MCUtil.toBlockPosition(event.getLocation()); ++ angle = event.getLocation().getYaw(); ++ forced = event.isForced(); ++ // Paper end - Add PlayerSetSpawnEvent + -+ if (newSpawn != null) { -+ resourcekey = ((CraftWorld) newSpawn.getWorld()).getHandle().dimension(); -+ blockposition = BlockPos.containing(newSpawn.getX(), newSpawn.getY(), newSpawn.getZ()); -+ f = newSpawn.getYaw(); -+ } else { -+ resourcekey = Level.OVERWORLD; -+ blockposition = null; -+ f = 0.0F; -+ } -+ // CraftBukkit end -+ if (blockposition != null) { -+ boolean flag2 = blockposition.equals(this.respawnPosition) && resourcekey.equals(this.respawnDimension); -+ -+ if (flag1 && !flag2) { - this.sendSystemMessage(Component.translatable("block.minecraft.set_spawn")); ++ if (event.willNotifyPlayer() && event.getNotification() != null) { // Paper - Add PlayerSetSpawnEvent ++ this.sendSystemMessage(PaperAdventure.asVanilla(event.getNotification())); // Paper - Add PlayerSetSpawnEvent } -- this.respawnPosition = pos; -- this.respawnDimension = dimension; -- this.respawnAngle = angle; -- this.respawnForced = forced; -+ this.respawnPosition = blockposition; -+ this.respawnDimension = resourcekey; -+ this.respawnAngle = f; -+ this.respawnForced = flag; - } else { - this.respawnPosition = null; - this.respawnDimension = Level.OVERWORLD; -@@ -2088,18 +2686,44 @@ + this.respawnPosition = pos; +@@ -2064,6 +2668,7 @@ + this.respawnForced = false; + } + ++ return true; // Paper - Add PlayerSetSpawnEvent + } + + public SectionPos getLastSectionPos() { +@@ -2088,18 +2693,44 @@ } @Override @@ -1585,7 +1591,7 @@ } this.awardStat(Stats.DROP); -@@ -2115,6 +2739,11 @@ +@@ -2115,6 +2746,11 @@ return null; } else { double d0 = this.getEyeY() - 0.30000001192092896D; @@ -1597,7 +1603,7 @@ ItemEntity entityitem = new ItemEntity(this.level(), this.getX(), d0, this.getZ(), stack); entityitem.setPickUpDelay(40); -@@ -2166,6 +2795,16 @@ +@@ -2166,6 +2802,16 @@ } public void loadGameTypes(@Nullable CompoundTag nbt) { @@ -1614,7 +1620,7 @@ this.gameMode.setGameModeForPlayer(this.calculateGameModeForNewPlayer(ServerPlayer.readPlayerMode(nbt, "playerGameType")), ServerPlayer.readPlayerMode(nbt, "previousPlayerGameType")); } -@@ -2275,9 +2914,15 @@ +@@ -2275,9 +2921,15 @@ @Override public void stopRiding() { @@ -1631,7 +1637,7 @@ if (entity instanceof LivingEntity entityliving) { Iterator iterator = entityliving.getActiveEffects().iterator(); -@@ -2375,10 +3020,12 @@ +@@ -2375,16 +3027,161 @@ return TicketType.ENDER_PEARL.timeout(); } @@ -1647,10 +1653,11 @@ } private static float calculateLookAtYaw(Vec3 respawnPos, BlockPos currentPos) { -@@ -2387,4 +3034,147 @@ + Vec3 vec3d1 = Vec3.atBottomCenterOf(currentPos).subtract(respawnPos).normalize(); + return (float) Mth.wrapDegrees(Mth.atan2(vec3d1.z, vec3d1.x) * 57.2957763671875D - 90.0D); - } - } ++ } ++ } + + // CraftBukkit start - Add per-player time and weather. + public long timeOffset = 0; @@ -1675,7 +1682,7 @@ + public void setPlayerWeather(WeatherType type, boolean plugin) { + if (!plugin && this.weather != null) { + return; -+ } + } + + if (plugin) { + this.weather = type; @@ -1686,7 +1693,7 @@ + } else { + this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.START_RAINING, 0)); + } -+ } + } + + private float pluginRainPosition; + private float pluginRainPositionPrevious; 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 22f75393aa..907a3b2c66 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 @@ -730,7 +730,7 @@ + // CraftBukkit end if (teleporttransition.missingRespawnBlock()) { entityplayer1.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.NO_RESPAWN_BLOCK_AVAILABLE, 0.0F)); -+ entityplayer1.setRespawnPosition(null, null, 0f, false, false, PlayerSpawnChangeEvent.Cause.RESET); // 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 } - int i = alive ? 1 : 0; diff --git a/paper-server/patches/sources/net/minecraft/world/level/block/RespawnAnchorBlock.java.patch b/paper-server/patches/sources/net/minecraft/world/level/block/RespawnAnchorBlock.java.patch index 22c28075e7..86e3e80aca 100644 --- a/paper-server/patches/sources/net/minecraft/world/level/block/RespawnAnchorBlock.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/level/block/RespawnAnchorBlock.java.patch @@ -1,15 +1,22 @@ --- a/net/minecraft/world/level/block/RespawnAnchorBlock.java +++ b/net/minecraft/world/level/block/RespawnAnchorBlock.java -@@ -88,7 +88,7 @@ +@@ -88,9 +88,14 @@ ServerPlayer entityplayer = (ServerPlayer) player; if (entityplayer.getRespawnDimension() != world.dimension() || !pos.equals(entityplayer.getRespawnPosition())) { - entityplayer.setRespawnPosition(world.dimension(), pos, 0.0F, false, true); -+ entityplayer.setRespawnPosition(world.dimension(), pos, 0.0F, false, true, org.bukkit.event.player.PlayerSpawnChangeEvent.Cause.RESPAWN_ANCHOR); // CraftBukkit ++ if (entityplayer.setRespawnPosition(world.dimension(), pos, 0.0F, false, true, com.destroystokyo.paper.event.player.PlayerSetSpawnEvent.Cause.RESPAWN_ANCHOR)) { // Paper - Add 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_SERVER; ++ // Paper start - Add PlayerSetSpawnEvent ++ } else { ++ return InteractionResult.FAIL; ++ } ++ // Paper end - Add PlayerSetSpawnEvent } -@@ -127,15 +127,16 @@ + } + +@@ -127,15 +132,16 @@ } private void explode(BlockState state, Level world, final BlockPos explodedPos) { @@ -28,7 +35,7 @@ @Override public Optional getBlockExplosionResistance(Explosion explosion, BlockGetter world, BlockPos pos, BlockState blockState, FluidState fluidState) { return pos.equals(explodedPos) && flag1 ? Optional.of(Blocks.WATER.getExplosionResistance()) : super.getBlockExplosionResistance(explosion, world, pos, blockState, fluidState); -@@ -143,7 +144,7 @@ +@@ -143,7 +149,7 @@ }; Vec3 vec3d = explodedPos.getCenter(); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java index ff8d6a0ceb..f363f885b3 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -1420,9 +1420,9 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @Override public void setRespawnLocation(Location location, boolean override) { if (location == null) { - this.getHandle().setRespawnPosition(null, null, 0.0F, override, false, PlayerSpawnChangeEvent.Cause.PLUGIN); + this.getHandle().setRespawnPosition(null, null, 0.0F, override, false, com.destroystokyo.paper.event.player.PlayerSetSpawnEvent.Cause.PLUGIN); // Paper - Add PlayerSetSpawnEvent } else { - this.getHandle().setRespawnPosition(((CraftWorld) location.getWorld()).getHandle().dimension(), CraftLocation.toBlockPosition(location), location.getYaw(), override, false, PlayerSpawnChangeEvent.Cause.PLUGIN); + this.getHandle().setRespawnPosition(((CraftWorld) location.getWorld()).getHandle().dimension(), CraftLocation.toBlockPosition(location), location.getYaw(), override, false, com.destroystokyo.paper.event.player.PlayerSetSpawnEvent.Cause.PLUGIN); // Paper - Add PlayerSetSpawnEvent } }