Move player to spawn point if spawn in unloaded world

If the playerdata contains an invalid world (missing, unloaded, invalid,
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>
This commit is contained in:
2277
2020-03-31 10:33:55 +01:00
parent d7f24e6729
commit dd3e099c9c
2 changed files with 154 additions and 127 deletions

View File

@@ -90,7 +90,7 @@
this.server = server;
this.registries = registryManager;
this.maxPlayers = maxPlayers;
@@ -148,27 +181,38 @@
@@ -148,44 +181,111 @@
}
public void placeNewPlayer(Connection connection, ServerPlayer player, CommonListenerCookie clientData) {
@@ -112,7 +112,10 @@
}
- optional = this.load(player);
- ResourceKey<Level> resourcekey = (ResourceKey) optional.flatMap((nbttagcompound) -> {
- DataResult dataresult = DimensionType.parseLegacy(new Dynamic(NbtOps.INSTANCE, nbttagcompound.get("Dimension")));
+ Optional<CompoundTag> optional = this.load(player); // CraftBukkit - decompile error
+ ResourceKey<Level> resourcekey = null; // Paper
+ // CraftBukkit start - Better rename detection
+ if (optional.isPresent()) {
+ CompoundTag nbttagcompound = optional.get();
@@ -122,25 +125,60 @@
+ }
+ }
+ // CraftBukkit end
ResourceKey<Level> resourcekey = (ResourceKey) optional.flatMap((nbttagcompound) -> {
- DataResult dataresult = DimensionType.parseLegacy(new Dynamic(NbtOps.INSTANCE, nbttagcompound.get("Dimension")));
+ // 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 (optional.isPresent()) {
+ // 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 (optional.get().contains("WorldUUIDMost") && optional.get().contains("WorldUUIDLeast")) {
+ bWorld = org.bukkit.Bukkit.getServer().getWorld(new UUID(optional.get().getLong("WorldUUIDMost"), optional.get().getLong("WorldUUIDLeast")));
+ } else if (optional.get().contains("world", net.minecraft.nbt.Tag.TAG_STRING)) { // Paper - legacy bukkit world name
+ bWorld = org.bukkit.Bukkit.getServer().getWorld(optional.get().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[0] = 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
+ resourcekey = optional.flatMap((nbttagcompound) -> {
+ // Paper end
+ DataResult<ResourceKey<Level>> dataresult = DimensionType.parseLegacy(new Dynamic(NbtOps.INSTANCE, nbttagcompound.get("Dimension"))); // CraftBukkit - decompile error
Logger logger = PlayerList.LOGGER;
Objects.requireNonNull(logger);
return dataresult.resultOrPartial(logger::error);
- return dataresult.resultOrPartial(logger::error);
- }).orElse(Level.OVERWORLD);
+ }).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[0] = result.isEmpty();
+ return result;
+ }).orElse(Level.OVERWORLD); // Paper - revert to vanilla default main world, this isn't an "invalid world" since no player data existed
+ }
+ // Paper end
ServerLevel worldserver = this.server.getLevel(resourcekey);
ServerLevel worldserver1;
@@ -179,13 +223,36 @@
if (worldserver == null) {
PlayerList.LOGGER.warn("Unknown respawn dimension {}, defaulting to overworld", resourcekey);
worldserver1 = this.server.overworld();
+ invalidPlayerWorld[0] = true; // Paper - reset to main world if no world with parsed value is found
} else {
worldserver1 = worldserver;
}
+ // Paper start - Entity#getEntitySpawnReason
+ if (optional.isEmpty()) {
+ 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 (optional.isEmpty() || invalidPlayerWorld[0]) {
+ // Paper end - reset to main world spawn if first spawn or invalid world
+ player.moveTo(player.adjustSpawnLocation(worldserver1, worldserver1.getSharedSpawnPos()).getBottomCenter(), 0.0F, 0.0F);
+ }
+ // Paper end - Entity#getEntitySpawnReason
@@ -173,7 +211,7 @@
ServerGamePacketListenerImpl playerconnection = new ServerGamePacketListenerImpl(this.server, connection, player, clientData);
connection.setupInboundProtocol(GameProtocols.SERVERBOUND_TEMPLATE.bind(RegistryFriendlyByteBuf.decorator(this.server.registryAccess())), playerconnection);
@@ -194,7 +261,9 @@
@@ -194,7 +294,9 @@
boolean flag1 = gamerules.getBoolean(GameRules.RULE_REDUCEDDEBUGINFO);
boolean flag2 = gamerules.getBoolean(GameRules.RULE_LIMITED_CRAFTING);
@@ -184,7 +222,7 @@
playerconnection.send(new ClientboundChangeDifficultyPacket(worlddata.getDifficulty(), worlddata.isDifficultyLocked()));
playerconnection.send(new ClientboundPlayerAbilitiesPacket(player.getAbilities()));
playerconnection.send(new ClientboundSetHeldSlotPacket(player.getInventory().selected));
@@ -213,8 +282,10 @@
@@ -213,8 +315,10 @@
} else {
ichatmutablecomponent = Component.translatable("multiplayer.player.joined.renamed", player.getDisplayName(), s);
}
@@ -196,7 +234,7 @@
playerconnection.teleport(player.getX(), player.getY(), player.getZ(), player.getYRot(), player.getXRot());
ServerStatus serverping = this.server.getStatus();
@@ -222,17 +293,85 @@
@@ -222,17 +326,85 @@
player.sendServerStatus(serverping);
}
@@ -287,7 +325,7 @@
}
public void updateEntireScoreboard(ServerScoreboard scoreboard, ServerPlayer player) {
@@ -269,30 +408,31 @@
@@ -269,30 +441,31 @@
}
public void addWorldborderListener(ServerLevel world) {
@@ -324,7 +362,7 @@
}
@Override
@@ -319,14 +459,15 @@
@@ -319,14 +492,15 @@
}
protected void save(ServerPlayer player) {
@@ -342,7 +380,7 @@
if (advancementdataplayer != null) {
advancementdataplayer.save();
@@ -334,95 +475,186 @@
@@ -334,95 +508,186 @@
}
@@ -525,13 +563,13 @@
+ if (this.players.size() >= this.maxPlayers && !this.canBypassPlayerLimit(gameprofile)) {
+ event.disallow(PlayerLoginEvent.Result.KICK_FULL, net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(org.spigotmc.SpigotConfig.serverFullMessage)); // Spigot // Paper - Adventure
+ }
}
+ }
+
+ this.cserver.getPluginManager().callEvent(event);
+ if (event.getResult() != PlayerLoginEvent.Result.ALLOWED) {
+ loginlistener.disconnect(io.papermc.paper.adventure.PaperAdventure.asVanilla(event.kickMessage())); // Paper - Adventure
+ return null;
+ }
}
+ return entity;
}
@@ -567,7 +605,7 @@
if (entityplayer1 != null) {
set.add(entityplayer1);
@@ -431,72 +663,160 @@
@@ -431,72 +696,160 @@
Iterator iterator1 = set.iterator();
while (iterator1.hasNext()) {
@@ -749,7 +787,7 @@
return entityplayer1;
}
@@ -516,15 +836,32 @@
@@ -516,15 +869,32 @@
}
public void sendPlayerPermissionLevel(ServerPlayer player) {
@@ -784,10 +822,14 @@
this.sendAllPlayerInfoIn = 0;
}
@@ -541,6 +878,25 @@
}
@@ -537,9 +907,28 @@
ServerPlayer entityplayer = (ServerPlayer) iterator.next();
entityplayer.connection.send(packet);
+ }
+
+ }
+
+ // CraftBukkit start - add a world/entity limited version
+ public void broadcastAll(Packet packet, net.minecraft.world.entity.player.Player entityhuman) {
+ for (int i = 0; i < this.players.size(); ++i) {
@@ -802,15 +844,14 @@
+ public void broadcastAll(Packet packet, Level world) {
+ for (int i = 0; i < world.players().size(); ++i) {
+ ((ServerPlayer) world.players().get(i)).connection.send(packet);
+ }
+
+ }
}
}
+ // CraftBukkit end
+
public void broadcastAll(Packet<?> packet, ResourceKey<Level> dimension) {
Iterator iterator = this.players.iterator();
@@ -554,7 +910,7 @@
@@ -554,7 +943,7 @@
}
@@ -819,7 +860,7 @@
PlayerTeam scoreboardteam = source.getTeam();
if (scoreboardteam != null) {
@@ -573,7 +929,7 @@
@@ -573,7 +962,7 @@
}
}
@@ -828,7 +869,7 @@
PlayerTeam scoreboardteam = source.getTeam();
if (scoreboardteam == null) {
@@ -619,7 +975,7 @@
@@ -619,7 +1008,7 @@
}
public void deop(GameProfile profile) {
@@ -837,7 +878,7 @@
ServerPlayer entityplayer = this.getPlayer(profile.getId());
if (entityplayer != null) {
@@ -643,36 +999,51 @@
@@ -643,35 +1032,50 @@
player.connection.send(new ClientboundEntityEventPacket(player, b0));
}
@@ -892,17 +933,16 @@
+ public void broadcast(@Nullable net.minecraft.world.entity.player.Player player, double x, double y, double z, double distance, ResourceKey<Level> worldKey, Packet<?> packet) {
for (int i = 0; i < this.players.size(); ++i) {
ServerPlayer entityplayer = (ServerPlayer) this.players.get(i);
+
+ // CraftBukkit start - Test if player receiving packet can see the source of the packet
+ if (player != null && !entityplayer.getBukkitEntity().canSee(player.getBukkitEntity())) {
+ continue;
+ }
+ // CraftBukkit end
+
if (entityplayer != player && entityplayer.level().dimension() == worldKey) {
double d4 = x - entityplayer.getX();
double d5 = y - entityplayer.getY();
@@ -687,10 +1058,12 @@
@@ -687,10 +1091,12 @@
}
public void saveAll() {
@@ -915,7 +955,7 @@
}
public UserWhiteList getWhiteList() {
@@ -712,15 +1085,19 @@
@@ -712,15 +1118,19 @@
public void reloadWhiteList() {}
public void sendLevelInfo(ServerPlayer player, ServerLevel world) {
@@ -939,7 +979,7 @@
}
player.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.LEVEL_CHUNKS_LOAD_START, 0.0F));
@@ -729,8 +1106,16 @@
@@ -729,8 +1139,16 @@
public void sendAllPlayerInfo(ServerPlayer player) {
player.inventoryMenu.sendAllDataToRemote();
@@ -957,7 +997,7 @@
}
public int getPlayerCount() {
@@ -746,6 +1131,7 @@
@@ -746,6 +1164,7 @@
}
public void setUsingWhiteList(boolean whitelistEnabled) {
@@ -965,7 +1005,7 @@
this.doWhiteList = whitelistEnabled;
}
@@ -786,11 +1172,35 @@
@@ -786,12 +1205,36 @@
}
public void removeAll() {
@@ -981,29 +1021,30 @@
+ for (ServerPlayer player : this.players) {
+ if (isRestarting) player.connection.disconnect(net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(org.spigotmc.SpigotConfig.restartMessage)); else // Paper
+ player.connection.disconnect(java.util.Objects.requireNonNullElseGet(this.server.server.shutdownMessage(), net.kyori.adventure.text.Component::empty)); // CraftBukkit - add custom shutdown message // Paper - Adventure
+ }
}
+ // CraftBukkit end
+
+ // Paper start - Configurable player collision; Remove collideRule team if it exists
+ if (this.collideRuleTeamName != null) {
+ final net.minecraft.world.scores.Scoreboard scoreboard = this.getServer().getLevel(Level.OVERWORLD).getScoreboard();
+ final PlayerTeam team = scoreboard.getPlayersTeam(this.collideRuleTeamName);
+ if (team != null) scoreboard.removePlayerTeam(team);
}
+ }
+ // Paper end - Configurable player collision
+ }
}
+ // CraftBukkit start
+ public void broadcastMessage(Component[] iChatBaseComponents) {
+ for (Component component : iChatBaseComponents) {
+ this.broadcastSystemMessage(component, false);
+ }
}
+ }
+ // CraftBukkit end
+
public void broadcastSystemMessage(Component message, boolean overlay) {
this.broadcastSystemMessage(message, (entityplayer) -> {
@@ -819,24 +1229,43 @@
return message;
@@ -819,24 +1262,43 @@
}
public void broadcastChatMessage(PlayerChatMessage message, ServerPlayer sender, ChatType.Bound params) {
@@ -1050,7 +1091,7 @@
}
if (flag1 && sender != null) {
@@ -845,20 +1274,27 @@
@@ -845,20 +1307,27 @@
}
@@ -1083,7 +1124,7 @@
Path path = file2.toPath();
if (FileUtil.isPathNormalized(path) && FileUtil.isPathPortable(path) && path.startsWith(file.getPath()) && file2.isFile()) {
@@ -867,7 +1303,7 @@
@@ -867,7 +1336,7 @@
}
serverstatisticmanager = new ServerStatsCounter(this.server, file1);
@@ -1092,7 +1133,7 @@
}
return serverstatisticmanager;
@@ -875,13 +1311,13 @@
@@ -875,13 +1344,13 @@
public PlayerAdvancements getPlayerAdvancements(ServerPlayer player) {
UUID uuid = player.getUUID();
@@ -1108,7 +1149,7 @@
}
advancementdataplayer.setPlayer(player);
@@ -932,15 +1368,28 @@
@@ -932,15 +1401,28 @@
}
public void reloadResources() {