mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-29 15:49:00 +01:00
Fix a bunch of stuff with player spawn locations (#9887)
If a playerdata doesn't contain a valid, loaded world, reset to the main world spawn point
This commit is contained in:
parent
5cfbe38b31
commit
c690244527
3 changed files with 107 additions and 64 deletions
|
@ -1,22 +0,0 @@
|
||||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
|
||||||
Date: Sat, 28 Oct 2023 23:21:49 -0700
|
|
||||||
Subject: [PATCH] Fix NPE when no valid world is found on legacy Players
|
|
||||||
|
|
||||||
|
|
||||||
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
|
|
||||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
|
||||||
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
|
|
||||||
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
|
|
||||||
@@ -0,0 +0,0 @@ public abstract class PlayerList {
|
|
||||||
Logger logger = PlayerList.LOGGER;
|
|
||||||
|
|
||||||
Objects.requireNonNull(logger);
|
|
||||||
- resourcekey = (ResourceKey) dataresult.resultOrPartial(logger::error).orElse(player.serverLevel().dimension()); // CraftBukkit - SPIGOT-7507: If no dimension, fall back to existing dimension loaded from "WorldUUID", which in turn defaults to World.OVERWORLD
|
|
||||||
+ resourcekey = (ResourceKey) dataresult.resultOrPartial(logger::error).orElse(player.serverLevel() != null ? player.serverLevel().dimension() : Level.OVERWORLD); // CraftBukkit - SPIGOT-7507: If no dimension, fall back to existing dimension loaded from "WorldUUID", which in turn defaults to World.OVERWORLD // Paper - account for null level
|
|
||||||
} else {
|
|
||||||
- resourcekey = player.serverLevel().dimension(); // CraftBukkit - SPIGOT-7507: If no dimension, fall back to existing dimension loaded from "WorldUUID", which in turn defaults to World.OVERWORLD
|
|
||||||
+ resourcekey = player.serverLevel() != null ? player.serverLevel().dimension() : Level.OVERWORLD; // CraftBukkit - SPIGOT-7507: If no dimension, fall back to existing dimension loaded from "WorldUUID", which in turn defaults to World.OVERWORLD // Paper - account for null level
|
|
||||||
}
|
|
||||||
|
|
||||||
ResourceKey<Level> resourcekey1 = resourcekey;
|
|
|
@ -3,25 +3,120 @@ From: 2277 <38501234+2277@users.noreply.github.com>
|
||||||
Date: Tue, 31 Mar 2020 10:33:55 +0100
|
Date: Tue, 31 Mar 2020 10:33:55 +0100
|
||||||
Subject: [PATCH] Move player to spawn point if spawn in unloaded world
|
Subject: [PATCH] Move player to spawn point if spawn in unloaded world
|
||||||
|
|
||||||
The code following this has better support for null worlds to move
|
If the playerdata contains an invalid world (missing, unloaded, invalid,
|
||||||
them back to the world spawn.
|
etc.), spawn the player at the spawn point of the main world.
|
||||||
|
|
||||||
|
Co-authored-by: Wyatt Childers <wchilders@nearce.com>
|
||||||
|
Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||||
|
|
||||||
|
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||||
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||||
|
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||||
|
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||||
|
@@ -0,0 +0,0 @@ public abstract class PlayerList {
|
||||||
|
}
|
||||||
|
|
||||||
|
CompoundTag nbttagcompound = this.load(player);
|
||||||
|
- ResourceKey resourcekey;
|
||||||
|
+ ResourceKey<Level> resourcekey = null; // Paper
|
||||||
|
// CraftBukkit start - Better rename detection
|
||||||
|
if (nbttagcompound != null && nbttagcompound.contains("bukkit")) {
|
||||||
|
CompoundTag bukkit = nbttagcompound.getCompound("bukkit");
|
||||||
|
@@ -0,0 +0,0 @@ public abstract class PlayerList {
|
||||||
|
}
|
||||||
|
// CraftBukkit end
|
||||||
|
|
||||||
|
+ // Paper start - move logic in Entity to here, to use bukkit supplied world UUID & reset to main world spawn if no valid world is found
|
||||||
|
+ boolean invalidPlayerWorld = false;
|
||||||
|
+ bukkitData: if (nbttagcompound != null) {
|
||||||
|
+ // The main way for bukkit worlds to store the world is the world UUID despite mojang adding custom worlds
|
||||||
|
+ final org.bukkit.World bWorld;
|
||||||
|
+ if (nbttagcompound.contains("WorldUUIDMost") && nbttagcompound.contains("WorldUUIDLeast")) {
|
||||||
|
+ bWorld = org.bukkit.Bukkit.getServer().getWorld(new UUID(nbttagcompound.getLong("WorldUUIDMost"), nbttagcompound.getLong("WorldUUIDLeast")));
|
||||||
|
+ } else if (nbttagcompound.contains("world", net.minecraft.nbt.Tag.TAG_STRING)) { // Paper - legacy bukkit world name
|
||||||
|
+ bWorld = org.bukkit.Bukkit.getServer().getWorld(nbttagcompound.getString("world"));
|
||||||
|
+ } else {
|
||||||
|
+ break bukkitData; // if neither of the bukkit data points exist, proceed to the vanilla migration section
|
||||||
|
+ }
|
||||||
|
+ if (bWorld != null) {
|
||||||
|
+ resourcekey = ((CraftWorld) bWorld).getHandle().dimension();
|
||||||
|
+ } else {
|
||||||
|
+ resourcekey = Level.OVERWORLD;
|
||||||
|
+ invalidPlayerWorld = true;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ if (resourcekey == null) { // only run the vanilla logic if we haven't found a world from the bukkit data
|
||||||
|
+ // Below is the vanilla way of getting the dimension, this is for migration from vanilla servers
|
||||||
|
+ // Paper end
|
||||||
|
if (nbttagcompound != null) {
|
||||||
|
DataResult<ResourceKey<Level>> dataresult = DimensionType.parseLegacy(new Dynamic(NbtOps.INSTANCE, nbttagcompound.get("Dimension"))); // CraftBukkit - decompile error
|
||||||
|
Logger logger = PlayerList.LOGGER;
|
||||||
|
|
||||||
|
Objects.requireNonNull(logger);
|
||||||
|
- resourcekey = (ResourceKey) dataresult.resultOrPartial(logger::error).orElse(player.serverLevel().dimension()); // CraftBukkit - SPIGOT-7507: If no dimension, fall back to existing dimension loaded from "WorldUUID", which in turn defaults to World.OVERWORLD
|
||||||
|
+ // Paper start - reset to main world spawn if no valid world is found
|
||||||
|
+ final Optional<ResourceKey<Level>> result = dataresult.resultOrPartial(logger::error);
|
||||||
|
+ invalidPlayerWorld = result.isEmpty();
|
||||||
|
+ resourcekey = result.orElse(Level.OVERWORLD);
|
||||||
|
+ // Paper end
|
||||||
|
} else {
|
||||||
|
- resourcekey = player.serverLevel().dimension(); // CraftBukkit - SPIGOT-7507: If no dimension, fall back to existing dimension loaded from "WorldUUID", which in turn defaults to World.OVERWORLD
|
||||||
|
+ resourcekey = Level.OVERWORLD; // Paper - revert to vanilla default main world, this isn't an "invalid world" since no player data existed
|
||||||
|
}
|
||||||
|
+ } // Paper
|
||||||
|
|
||||||
|
ResourceKey<Level> resourcekey1 = resourcekey;
|
||||||
|
ServerLevel worldserver = this.server.getLevel(resourcekey1);
|
||||||
|
@@ -0,0 +0,0 @@ public abstract class PlayerList {
|
||||||
|
if (worldserver == null) {
|
||||||
|
PlayerList.LOGGER.warn("Unknown respawn dimension {}, defaulting to overworld", resourcekey1);
|
||||||
|
worldserver1 = this.server.overworld();
|
||||||
|
+ invalidPlayerWorld = true; // Paper - reset to main world if no world with parsed value is found
|
||||||
|
} else {
|
||||||
|
worldserver1 = worldserver;
|
||||||
|
}
|
||||||
|
@@ -0,0 +0,0 @@ public abstract class PlayerList {
|
||||||
|
// Paper start
|
||||||
|
if (nbttagcompound == null) {
|
||||||
|
player.spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT; // set Player SpawnReason to DEFAULT on first login
|
||||||
|
+ // Paper start - reset to main world spawn if first spawn or invalid world
|
||||||
|
+ }
|
||||||
|
+ if (nbttagcompound == null || invalidPlayerWorld) {
|
||||||
|
+ // Paper end
|
||||||
|
player.fudgeSpawnLocation(worldserver1); // only move to spawn on first login, otherwise, stay where you are....
|
||||||
|
}
|
||||||
|
// Paper end
|
||||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||||
@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
|
@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
|
||||||
bworld = server.getWorld(worldName);
|
}
|
||||||
}
|
// CraftBukkit end
|
||||||
|
|
||||||
|
- // CraftBukkit start - Reset world
|
||||||
|
- if (this instanceof ServerPlayer) {
|
||||||
|
- Server server = Bukkit.getServer();
|
||||||
|
- org.bukkit.World bworld = null;
|
||||||
|
-
|
||||||
|
- // TODO: Remove World related checks, replaced with WorldUID
|
||||||
|
- String worldName = nbt.getString("world");
|
||||||
|
-
|
||||||
|
- if (nbt.contains("WorldUUIDMost") && nbt.contains("WorldUUIDLeast")) {
|
||||||
|
- UUID uid = new UUID(nbt.getLong("WorldUUIDMost"), nbt.getLong("WorldUUIDLeast"));
|
||||||
|
- bworld = server.getWorld(uid);
|
||||||
|
- } else {
|
||||||
|
- bworld = server.getWorld(worldName);
|
||||||
|
- }
|
||||||
|
-
|
||||||
- if (bworld == null) {
|
- if (bworld == null) {
|
||||||
- bworld = ((org.bukkit.craftbukkit.CraftServer) server).getServer().getLevel(Level.OVERWORLD).getWorld();
|
- bworld = ((org.bukkit.craftbukkit.CraftServer) server).getServer().getLevel(Level.OVERWORLD).getWorld();
|
||||||
- }
|
- }
|
||||||
+ // Paper start - Move player to spawn point if spawn in unloaded world
|
-
|
||||||
+// if (bworld == null) {
|
- ((ServerPlayer) this).setLevel(bworld == null ? null : ((CraftWorld) bworld).getHandle());
|
||||||
+// bworld = ((org.bukkit.craftbukkit.CraftServer) server).getServer().getWorldServer(World.OVERWORLD).getWorld();
|
- }
|
||||||
+// }
|
+ // CraftBukkit start
|
||||||
+ // Paper end - Move player to spawn point if spawn in unloaded world
|
+ // Paper - move world parsing/loading to PlayerList#placeNewPlayer
|
||||||
|
this.getBukkitEntity().readBukkitValues(nbt);
|
||||||
((ServerPlayer) this).setLevel(bworld == null ? null : ((CraftWorld) bworld).getHandle());
|
if (nbt.contains("Bukkit.invisible")) {
|
||||||
}
|
boolean bukkitInvisible = nbt.getBoolean("Bukkit.invisible");
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Wyatt Childers <wchilders@nearce.com>
|
|
||||||
Date: Fri, 3 Jul 2020 14:57:05 -0400
|
|
||||||
Subject: [PATCH] Spawn player in correct world on login
|
|
||||||
|
|
||||||
|
|
||||||
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
|
|
||||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
|
||||||
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
|
|
||||||
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
|
|
||||||
@@ -0,0 +0,0 @@ public abstract class PlayerList {
|
|
||||||
}
|
|
||||||
// CraftBukkit end
|
|
||||||
|
|
||||||
- if (nbttagcompound != null) {
|
|
||||||
+ // Paper start - move logic in Entity to here, to use bukkit supplied world UUID.
|
|
||||||
+ if (nbttagcompound != null && nbttagcompound.contains("WorldUUIDMost") && nbttagcompound.contains("WorldUUIDLeast")) {
|
|
||||||
+ UUID uid = new UUID(nbttagcompound.getLong("WorldUUIDMost"), nbttagcompound.getLong("WorldUUIDLeast"));
|
|
||||||
+ org.bukkit.World bWorld = org.bukkit.Bukkit.getServer().getWorld(uid);
|
|
||||||
+ if (bWorld != null) {
|
|
||||||
+ resourcekey = ((CraftWorld) bWorld).getHandle().dimension();
|
|
||||||
+ } else {
|
|
||||||
+ resourcekey = Level.OVERWORLD;
|
|
||||||
+ }
|
|
||||||
+ } else if (nbttagcompound != null) {
|
|
||||||
+ // Vanilla migration support
|
|
||||||
+ // Paper end
|
|
||||||
DataResult<ResourceKey<Level>> dataresult = DimensionType.parseLegacy(new Dynamic(NbtOps.INSTANCE, nbttagcompound.get("Dimension"))); // CraftBukkit - decompile error
|
|
||||||
Logger logger = PlayerList.LOGGER;
|
|
||||||
|
|
Loading…
Reference in a new issue