mirror of
https://github.com/Minestom/Minestom.git
synced 2025-01-20 07:02:32 +01:00
Fix respawning players falling into the void (#1454)
This commit is contained in:
parent
9dab3183e5
commit
6316eeb90e
@ -431,7 +431,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
||||
setOnFire(false);
|
||||
refreshHealth();
|
||||
sendPacket(new RespawnPacket(getDimensionType().toString(), getDimensionType().getName().asString(),
|
||||
0, gameMode, gameMode, false, levelFlat, true));
|
||||
0, gameMode, gameMode, false, levelFlat, true));
|
||||
|
||||
PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(this);
|
||||
EventDispatcher.call(respawnEvent);
|
||||
@ -439,8 +439,21 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
||||
refreshIsDead(false);
|
||||
updatePose();
|
||||
|
||||
// Runnable called when teleportation is successful (after loading and sending necessary chunk)
|
||||
teleport(respawnEvent.getRespawnPosition()).thenRun(this::refreshAfterTeleport);
|
||||
Pos respawnPosition = respawnEvent.getRespawnPosition();
|
||||
|
||||
// The client unloads chunks when respawning, so resend all chunks next to spawn
|
||||
ChunkUtils.forChunksInRange(respawnPosition, MinecraftServer.getChunkViewDistance(), (chunkX, chunkZ) ->
|
||||
this.instance.loadOptionalChunk(chunkX, chunkZ).thenAccept(chunk -> {
|
||||
try {
|
||||
if (chunk != null) {
|
||||
chunk.sendChunk(this);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
MinecraftServer.getExceptionManager().handleException(e);
|
||||
}
|
||||
}));
|
||||
chunksLoadedByClient = new Vec(respawnPosition.chunkX(), respawnPosition.chunkZ());
|
||||
teleport(respawnPosition).thenRun(this::refreshAfterTeleport);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,73 @@
|
||||
package net.minestom.server.entity.player;
|
||||
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.coordinate.Pos;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.network.packet.client.play.ClientStatusPacket;
|
||||
import net.minestom.server.network.packet.server.play.ChunkDataPacket;
|
||||
import net.minestom.server.network.packet.server.play.UnloadChunkPacket;
|
||||
import net.minestom.server.utils.chunk.ChunkUtils;
|
||||
import net.minestom.testing.Env;
|
||||
import net.minestom.testing.EnvTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
|
||||
@EnvTest
|
||||
public class PlayerRespawnChunkTest {
|
||||
|
||||
|
||||
@Test
|
||||
public void testChunkUnloadsOnRespawn(Env env) {
|
||||
var instance = env.createFlatInstance();
|
||||
var connection = env.createConnection();
|
||||
Player player = connection.connect(instance, new Pos(0, 40, 0)).join();
|
||||
player.teleport(new Pos(32, 40, 32)).join();
|
||||
|
||||
var unloadChunkTracker = connection.trackIncoming(UnloadChunkPacket.class);
|
||||
player.setHealth(0);
|
||||
player.respawn();
|
||||
// Since client unloads the chunks, we shouldn't receive any unload packets
|
||||
unloadChunkTracker.assertCount(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChunkReloadCount(Env env) {
|
||||
var instance = env.createFlatInstance();
|
||||
var connection = env.createConnection();
|
||||
Player player = connection.connect(instance, new Pos(0, 40, 0)).join();
|
||||
|
||||
var loadChunkTracker = connection.trackIncoming(ChunkDataPacket.class);
|
||||
player.setHealth(0);
|
||||
player.respawn();
|
||||
// Player should have all their chunks reloaded
|
||||
int chunkLoads = ChunkUtils.getChunkCount(MinecraftServer.getChunkViewDistance());
|
||||
loadChunkTracker.assertCount(chunkLoads);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPlayerTryRespawn(Env env) {
|
||||
var instance = env.createFlatInstance();
|
||||
var connection = env.createConnection();
|
||||
Player player = connection.connect(instance, new Pos(0, 40, 0)).join();
|
||||
|
||||
var loadChunkTracker = connection.trackIncoming(ChunkDataPacket.class);
|
||||
player.setHealth(0);
|
||||
player.addPacketToQueue(new ClientStatusPacket(ClientStatusPacket.Action.PERFORM_RESPAWN));
|
||||
player.interpretPacketQueue();
|
||||
List<ChunkDataPacket> dataPacketList = loadChunkTracker.collect();
|
||||
Set<ChunkDataPacket> duplicateCheck = new HashSet<>();
|
||||
int chunkLoads = ChunkUtils.getChunkCount(MinecraftServer.getChunkViewDistance());
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user