Fix entities vanishing upon respawn (#1497)

This commit is contained in:
GreatWyrm 2022-11-26 15:23:39 -05:00 committed by GitHub
parent 77be05085d
commit 27f3b5d4ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 17 additions and 7 deletions

View File

@ -455,7 +455,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
Pos respawnPosition = respawnEvent.getRespawnPosition();
// The client unloads chunks when respawning, so resend all chunks next to spawn
ChunkUtils.forChunksInRange(respawnPosition, MinecraftServer.getChunkViewDistance(), (chunkX, chunkZ) ->
ChunkUtils.forChunksInRange(respawnPosition, Math.min(MinecraftServer.getChunkViewDistance(), settings.getViewDistance()), (chunkX, chunkZ) ->
this.instance.loadOptionalChunk(chunkX, chunkZ).thenAccept(chunk -> {
try {
if (chunk != null) {
@ -466,6 +466,14 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
}
}));
chunksLoadedByClient = new Vec(respawnPosition.chunkX(), respawnPosition.chunkZ());
// Client also needs all entities resent to them, since those are unloaded as well
this.instance.getEntityTracker().nearbyEntitiesByChunkRange(respawnPosition, Math.min(MinecraftServer.getChunkViewDistance(), settings.getViewDistance()),
EntityTracker.Target.ENTITIES, entity -> {
// Skip refreshing self with a new viewer
if (!entity.getUuid().equals(uuid)) {
entity.updateNewViewer(this);
}
});
teleport(respawnPosition).thenRun(this::refreshAfterTeleport);
}
@ -2181,7 +2189,8 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
public void refresh(String locale, byte viewDistance, ChatMessageType chatMessageType, boolean chatColors,
byte displayedSkinParts, MainHand mainHand, boolean enableTextFiltering, boolean allowServerListings) {
this.locale = locale;
this.viewDistance = viewDistance;
// Clamp viewDistance to valid bounds
this.viewDistance = (byte) MathUtils.clamp(viewDistance, 2, 32);
this.chatMessageType = chatMessageType;
this.chatColors = chatColors;
this.displayedSkinParts = displayedSkinParts;

View File

@ -8,8 +8,8 @@ import net.minestom.server.network.packet.client.play.ClientSettingsPacket;
public final class SettingsListener {
public static void listener(ClientSettingsPacket packet, Player player) {
Player.PlayerSettings settings = player.getSettings();
final byte viewDistance = (byte) Math.abs(packet.viewDistance());
settings.refresh(packet.locale(), viewDistance, packet.chatMessageType(), packet.chatColors(), packet.displayedSkinParts(), packet.mainHand(), packet.enableTextFiltering(), packet.allowsListing());
// Since viewDistance bounds checking is performed in the refresh function, it is not necessary to check it here
settings.refresh(packet.locale(), packet.viewDistance(), packet.chatMessageType(), packet.chatColors(), packet.displayedSkinParts(), packet.mainHand(), packet.enableTextFiltering(), packet.allowsListing());
EventDispatcher.call(new PlayerSettingsChangeEvent(player));
}
}

View File

@ -45,7 +45,7 @@ public class PlayerRespawnChunkIntegrationTest {
player.setHealth(0);
player.respawn();
// Player should have all their chunks reloaded
int chunkLoads = ChunkUtils.getChunkCount(MinecraftServer.getChunkViewDistance());
int chunkLoads = ChunkUtils.getChunkCount(Math.min(MinecraftServer.getChunkViewDistance(), player.getSettings().getViewDistance()));
loadChunkTracker.assertCount(chunkLoads);
}
@ -61,12 +61,13 @@ public class PlayerRespawnChunkIntegrationTest {
player.interpretPacketQueue();
List<ChunkDataPacket> dataPacketList = loadChunkTracker.collect();
Set<ChunkDataPacket> duplicateCheck = new HashSet<>();
int chunkLoads = ChunkUtils.getChunkCount(MinecraftServer.getChunkViewDistance());
int actualViewDistance = Math.min(MinecraftServer.getChunkViewDistance(), player.getSettings().getViewDistance());
int chunkLoads = ChunkUtils.getChunkCount(actualViewDistance);
loadChunkTracker.assertCount(chunkLoads);
for (ChunkDataPacket packet : dataPacketList) {
assertFalse(duplicateCheck.contains(packet));
duplicateCheck.add(packet);
assertTrue(Math.abs(packet.chunkX()) <= MinecraftServer.getChunkViewDistance() && Math.abs(packet.chunkZ()) <= MinecraftServer.getChunkViewDistance());
assertTrue(Math.abs(packet.chunkX()) <= actualViewDistance && Math.abs(packet.chunkZ()) <= actualViewDistance);
}
}
}