Skip to content

Commit

Permalink
Fix inconsistencies between offline/online spawn position getter
Browse files Browse the repository at this point in the history
  • Loading branch information
Lulu13022002 committed Jan 12, 2025
1 parent 86c6308 commit c02f0ef
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 30 deletions.
20 changes: 17 additions & 3 deletions paper-api/src/main/java/org/bukkit/OfflinePlayer.java
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ public default BanEntry banPlayer(@Nullable String reason, @Nullable java.util.D
@Nullable
@Deprecated(since = "1.20.4")
public Location getBedSpawnLocation();

// Paper start
/**
* Gets the last date and time that this player logged into the server.
Expand All @@ -290,13 +291,26 @@ public default BanEntry banPlayer(@Nullable String reason, @Nullable java.util.D
// Paper end

/**
* Gets the Location where the player will spawn at, null if they
* Gets the Location where the player will spawn at, {@code null} if they
* don't have a valid respawn point.
*
* @return respawn location if exists, otherwise {@code null}.
*/
@Nullable
default Location getRespawnLocation() {
return this.getRespawnLocation(false); // keep old behavior for offline players
}

/**
* Gets the Location where the player will spawn at, {@code null} if they
* don't have a valid respawn point.
*
* @return respawn location if exists, otherwise null.
* @param load load the current location to retrieve the exact position of the spawn block
* and check if this position is still valid or not
* @return respawn location if exists, otherwise {@code null}.
*/
@Nullable
public Location getRespawnLocation();
Location getRespawnLocation(boolean load);

/**
* Increments the given statistic for this player.
Expand Down
6 changes: 4 additions & 2 deletions paper-api/src/main/java/org/bukkit/entity/HumanEntity.java
Original file line number Diff line number Diff line change
Expand Up @@ -469,9 +469,11 @@ default Location getPotentialBedLocation() {
* to validate if the current respawn location is still valid.
*
* @return respawn location if exists, otherwise null.
* @deprecated this method doesn't take in account the respawn angle, use
* {@link Player#getRespawnLocation(boolean)} with load = false instead
*/
@Nullable
Location getPotentialRespawnLocation();
@Deprecated
@Nullable Location getPotentialRespawnLocation();
// Paper end
// Paper start
/**
Expand Down
10 changes: 3 additions & 7 deletions paper-api/src/main/java/org/bukkit/entity/Player.java
Original file line number Diff line number Diff line change
Expand Up @@ -560,15 +560,11 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
@Deprecated(since = "1.20.4")
public Location getBedSpawnLocation();

/**
* Gets the Location where the player will spawn at, null if they
* don't have a valid respawn point.
*
* @return respawn location if exists, otherwise null.
*/
@Nullable
@Override
public Location getRespawnLocation();
default Location getRespawnLocation() {
return this.getRespawnLocation(true);
}

/**
* Sets the Location where the player will spawn at their bed.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import net.minecraft.core.GlobalPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.NbtOps;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.players.UserWhiteListEntry;
import net.minecraft.stats.ServerStatsCounter;
import net.minecraft.world.level.storage.PlayerDataStorage;
Expand All @@ -28,12 +30,11 @@
import org.bukkit.configuration.serialization.ConfigurationSerializable;
import org.bukkit.configuration.serialization.SerializableAs;
import org.bukkit.craftbukkit.entity.memory.CraftMemoryMapper;
import org.bukkit.craftbukkit.profile.CraftPlayerProfile;
import org.bukkit.craftbukkit.util.CraftLocation;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.metadata.MetadataValue;
import org.bukkit.plugin.Plugin;
import org.bukkit.profile.PlayerProfile;

@SerializableAs("Player")
public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializable {
Expand Down Expand Up @@ -392,12 +393,11 @@ public Location getBedSpawnLocation() {
}

@Override
public Location getRespawnLocation() {
public Location getRespawnLocation(boolean load) {
CompoundTag data = this.getData();
if (data == null) return null;

if (data.contains("SpawnX") && data.contains("SpawnY") && data.contains("SpawnZ")) {
// Paper start - fix wrong world
final float respawnAngle = data.getFloat("SpawnAngle");
org.bukkit.World spawnWorld = this.server.getWorld(data.getString("SpawnWorld")); // legacy
if (data.contains("SpawnDimension")) {
Expand All @@ -409,8 +409,15 @@ public Location getRespawnLocation() {
if (spawnWorld == null) {
return null;
}
return new Location(spawnWorld, data.getInt("SpawnX"), data.getInt("SpawnY"), data.getInt("SpawnZ"), respawnAngle, 0);
// Paper end
net.minecraft.core.BlockPos respawnPos = new net.minecraft.core.BlockPos(data.getInt("SpawnX"), data.getInt("SpawnY"), data.getInt("SpawnZ"));
if (!load) {
return CraftLocation.toBukkit(respawnPos, spawnWorld, respawnAngle, 0);
}
Optional<ServerPlayer.RespawnPosAngle> spawnLoc = ServerPlayer.findRespawnAndUseSpawnBlock(((CraftWorld) spawnWorld).getHandle(), respawnPos, respawnAngle, true, false);
if (spawnLoc.isPresent()) {
ServerPlayer.RespawnPosAngle resolvedPos = spawnLoc.get();
return CraftLocation.toBukkit(resolvedPos.position(), spawnWorld, resolvedPos.yaw(), 0);
}
}
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,6 @@
import org.bukkit.craftbukkit.map.RenderData;
import org.bukkit.craftbukkit.potion.CraftPotionEffectType;
import org.bukkit.craftbukkit.potion.CraftPotionUtil;
import org.bukkit.craftbukkit.profile.CraftPlayerProfile;
import org.bukkit.craftbukkit.scoreboard.CraftScoreboard;
import org.bukkit.craftbukkit.util.CraftChatMessage;
import org.bukkit.craftbukkit.util.CraftLocation;
Expand All @@ -181,7 +180,6 @@
import org.bukkit.event.player.PlayerHideEntityEvent;
import org.bukkit.event.player.PlayerRegisterChannelEvent;
import org.bukkit.event.player.PlayerShowEntityEvent;
import org.bukkit.event.player.PlayerSpawnChangeEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.event.player.PlayerUnregisterChannelEvent;
import org.bukkit.inventory.EquipmentSlot;
Expand All @@ -194,7 +192,6 @@
import org.bukkit.plugin.messaging.StandardMessenger;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.profile.PlayerProfile;
import org.bukkit.scoreboard.Scoreboard;
import org.jetbrains.annotations.NotNull;

Expand Down Expand Up @@ -1556,15 +1553,18 @@ public Location getBedSpawnLocation() {
}

@Override
public Location getRespawnLocation() {
public Location getRespawnLocation(boolean load) {
ServerLevel world = this.getHandle().server.getLevel(this.getHandle().getRespawnDimension());
BlockPos bed = this.getHandle().getRespawnPosition();
BlockPos respawnPos = this.getHandle().getRespawnPosition();

if (world != null && bed != null) {
Optional<ServerPlayer.RespawnPosAngle> spawnLoc = ServerPlayer.findRespawnAndUseSpawnBlock(world, bed, this.getHandle().getRespawnAngle(), this.getHandle().isRespawnForced(), true);
if (world != null && respawnPos != null) {
if (!load) {
return CraftLocation.toBukkit(respawnPos, world.getWorld(), this.getHandle().getRespawnAngle(), 0);
}
Optional<ServerPlayer.RespawnPosAngle> spawnLoc = ServerPlayer.findRespawnAndUseSpawnBlock(world, respawnPos, this.getHandle().getRespawnAngle(), this.getHandle().isRespawnForced(), false);
if (spawnLoc.isPresent()) {
ServerPlayer.RespawnPosAngle vec = spawnLoc.get();
return CraftLocation.toBukkit(vec.position(), world.getWorld(), vec.yaw(), 0);
ServerPlayer.RespawnPosAngle resolvedPos = spawnLoc.get();
return CraftLocation.toBukkit(resolvedPos.position(), world.getWorld(), resolvedPos.yaw(), 0);
}
}
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public static Location toBukkit(BlockPos blockPosition) {
public static Location toBukkit(BlockPos blockPosition, net.minecraft.world.level.Level world) {
return CraftLocation.toBukkit(blockPosition, world.getWorld(), 0.0F, 0.0F);
}

public static Location toBukkit(BlockPos blockPosition, World world) {
return CraftLocation.toBukkit(blockPosition, world, 0.0F, 0.0F);
}
Expand All @@ -40,16 +41,14 @@ public static BlockPos toBlockPosition(Location location) {
return new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ());
}

// Paper start
public static net.minecraft.core.GlobalPos toGlobalPos(Location location) {
return net.minecraft.core.GlobalPos.of(((org.bukkit.craftbukkit.CraftWorld) location.getWorld()).getHandle().dimension(), toBlockPosition(location));
}

public static Location fromGlobalPos(net.minecraft.core.GlobalPos globalPos) {
BlockPos pos = globalPos.pos();
return new org.bukkit.Location(net.minecraft.server.MinecraftServer.getServer().getLevel(globalPos.dimension()).getWorld(), pos.getX(), pos.getY(), pos.getZ());
return new Location(net.minecraft.server.MinecraftServer.getServer().getLevel(globalPos.dimension()).getWorld(), pos.getX(), pos.getY(), pos.getZ());
}
// Paper end

public static Vec3 toVec3D(Location location) {
return new Vec3(location.getX(), location.getY(), location.getZ());
Expand Down

0 comments on commit c02f0ef

Please sign in to comment.