Skip to content
mc-protocol
Esc
↑↓navigate↵open⌘Jpreview
On this page

Events

Every event Server, Client, and Proxy emit, with their arguments.

Server, Client, and Proxy extend Node’s EventEmitter. Server re-emits most Client events with the client prepended as the first argument, so you can listen in one place instead of subscribing per connection.

Server

Event Arguments When
Server:Ready – Listening socket is open.
Server:Error error The listening socket failed (port in use, and so on).
Server:Close – The listening socket closed.
connection client A TCP connection was accepted. Nothing has been parsed yet.
packet client, packet A packet was parsed and its automatic initialization responses completed, if enabled. Not emitted for failed initialization or handled automatic keep-alive replies. packet is { id, name, data }.
<PacketName> client, data, packet Every packet with this name across all states, for example server.on("KeepAlive", …).
<State>/<PacketName> client, data, packet The same packet filtered by the state in which it was decoded, for example server.on("Config/KeepAlive", …). State names are Handshake, Status, Login, Config, and Play.
login client, session The client sent LoginAcknowledged; state is now config.
playerJoin client, session The client sent FinishConfiguration; state is now play. Fires once per connection.
playerLeave client A client that had joined disconnected. Fires before disconnect.
disconnect client Any client disconnected, joined or not.
stateChange client, { direction, from, to } Either direction changed state.
versionRejected client, protocol The handshake asked for a protocol not in server.versions with a login or transfer intent. A LoginDisconnect was sent and the socket ended.
keepAlive client, { keepAliveId, latency } A KeepAlive reply matched an outstanding ping. latency is in milliseconds. Only with autoKeepAlive.
Client:Error client, error A per-client failure: packet parse error, autoInit throwing, unexpected or timed-out keep-alive. The client is destroyed on keep-alive failures.

server.clients is a Set<Client> of live connections.

Client

Packets

Event Arguments When
packet packet A packet was parsed. packet is { id, name, data }.
<PacketName> data, packet Every packet with this name across all states, for example client.on("KeepAlive", …).
<State>/<PacketName> data, packet The same packet filtered by the state in which it was decoded, for example client.on("Config/KeepAlive", …). State names are Handshake, Status, Login, Config, and Play.
packetSent { name, data } After sendPacket wrote to the socket.
Packet:Error error Incoming bytes could not be parsed. The connection stays open.

Lifecycle

Event Arguments When
login session LoginAcknowledged passed through; state is now config.
playerJoin session Entered play for the first time.
stateChange { direction, from, to } direction is "incoming" or "outgoing".
compression threshold LoginCompression set the threshold. null disables.
version protocol The packet tables switched to another built-in version after Intension.
versionRejected protocol Server side: the handshake protocol is not accepted and the connection was refused.

Socket

Event Arguments When
Socket:Ready – Connected (client side) or attached (server side).
Socket:Data buffer Raw bytes arrived, before parsing.
Socket:End – The peer half-closed.
Socket:Close hadError The socket is gone.
Socket:Error error Underlying net.Socket error.

Async listeners

sendPacket is async and event listeners are called synchronously, so a listener that awaits can reject after the emitter has moved on. Attach a .catch:

server.on("Play/PlayerAction", (client, data, packet) => {
  handle(client, data, packet).catch((error) => {
    console.error(error);
    client.destroy();
  });
});

Packets are dispatched in order, but a listener that awaits does not block the next packet from being parsed. If ordering between two handlers matters, serialize them yourself.

Proxy

Proxy emits its own lifecycle events. Packet interception uses proxy.Client.on(name, handler) and proxy.Server.on(name, handler) instead; those are not listed here. See Building a proxy.

Event Arguments When
Proxy:Ready – The player-facing listener is open.
Proxy:Error error The player-facing listener failed.
Proxy:Close – The player-facing listener closed.
connection player, upstream A player connected and an upstream Client was created. The upstream socket may not be ready yet.
disconnect player, upstream The player socket closed. The upstream connection is destroyed.
Upstream:Error player, error The upstream socket or packet parse failed. A socket error also destroys the player.
Client:Error player, error The player connection failed to parse a packet.

proxy.connections is a Map<Client, Client> from player to upstream.

session

login and playerJoin hand you client.session. Every field is optional until the matching packet has passed through:

interface ClientSession {
  protocol?: number;       // from Intension
  serverAddress?: string;  // from Intension
  serverPort?: number;     // from Intension
  username?: string;       // from Hello, then LoginFinished
  uuid?: string;           // from Hello, then LoginFinished
  profile?: unknown;       // gameProfile from LoginFinished
}

Was this page helpful?