Login
Play 0x31, server → client.
play · 0x31 · clientbound (server → client)
Starts the play state; this is the ‘join game’ packet. It carries the player’s entityId, hardcore flag, dimension list, view and simulation distances, and the spawn info for the current dimension (dimension type, name, seed hash, game mode, and so on). The server sends it once, right after the configuration state finishes, and the client uses it to set up the world before receiving chunks.
Sent by the server, read by the client. Listen for it with client.on("Login", (data) => …) on the receiving side.
Fields
| Field | Type | Notes |
|---|---|---|
entityId |
Int | |
isHardcore |
Boolean | |
worldNames |
Array | |
maxPlayers |
VarInt | |
viewDistance |
VarInt | |
simulationDistance |
VarInt | |
reducedDebugInfo |
Boolean | |
enableRespawnScreen |
Boolean | |
doLimitedCrafting |
Boolean | |
worldState |
SpawnInfo | |
onlineMode |
Boolean | |
enforcesSecureChat |
Boolean |
Send it
const WORLD = "minecraft:overworld";
await client.sendPacket("Login", {
entityId: 1,
isHardcore: false,
worldNames: [WORLD],
maxPlayers: 20,
viewDistance: 8,
simulationDistance: 2,
reducedDebugInfo: false,
enableRespawnScreen: true,
doLimitedCrafting: false,
worldState: {
dimension: 0, // index into the dimension_type registry
name: WORLD,
hashedSeed: 0n,
gamemode: 1, // creative
previousGamemode: 255, // none
isDebug: false,
isFlat: true,
death: null,
portalCooldown: 0,
seaLevel: -63,
},
onlineMode: false,
enforcesSecureChat: false,
});
The first packet after entering play. entityId becomes the player’s own ID; reuse it in entity packets. worldState.dimension is the index of the dimension type in the registry sent during configuration. See Building a server for the full spawn sequence.
Field aliases listed under Notes are accepted as alternative keys when writing.
Source: src/Core/Versions/776/Packets/play/clientbound/Login.ts