-
Notifications
You must be signed in to change notification settings - Fork 6
Writing a Client
The protocol module is designed to be a low-level implementation, leaving much of the logic to the developer. By default, CraftLib will not automatically respond to or process any packets from the server.
Please note that CraftLib currently lacks an authentication module. This is planned, however at this time you will have to fetch an access token yourself.
The first step of connecting to a Minecraft server is using the connection builder. This is a suspend function which defines the initial packet handler and establishes the connection with the remote host.
The below code will connect to a Minecraft server running locally on port 25565 and log any packets the server sent. However, since there is no packet handling defined, no packets will be logged.
suspend fun main() {
// This will connect to a Minecraft server running on
// localhost with the port 25565.
MinecraftProtocol.connect(InetAddress.getByName("localhost"), 25565) {
// When true, this will install an additional handler in the connection to
// print additional information about packets being sent/received
// In a production environment this should usually be set to false.
debug = true
// If this is greater than 0, an additional handler
// will be added to close the connection if no packets
// have been read/written in the duration below (30s)
timeout = 30
// When true, the connect function will block until
// the connection has fully terminated.
connectSync = true
// Sets the TCP No Delay value to true if this is defined.
noDelay = true
// This sets the initial packet handler which should process
// the handshake packets. You will learn
// about this in the next step.
handler = CustomPacketHandler
}
}
To actually communicate with a Minecraft server, you will need to define a custom packet handler. This handler controls what your client does after it has been connected, including catching exceptions, sending initial packets and reading from the server.
The example below will execute the most basic login flow in offline (cracked) mode, switching into the play state and logging all packets.
object CustomPacketHandler : PacketHandler {
override fun connected(connection: NettyConnection) {
// Configure packets to use the Minecraft 1.8 format
connection.version = ProtocolVersion.MC1_8
// The initial state should be set to handshake so that we
// can send the ClientHandshakePacket and have it encode properly
connection.state = MinecraftProtocol.HANDSHAKE
// Send the handshake packet, providing the address as localhost,
// port as 25565 and setting our next target state as LOGIN.
// This allows us to send the login start packet and begin authenticating
connection.send(
ClientHandshakePacket(
ProtocolVersion.MC1_8,
"localhost",
25565,
MinecraftProtocol.LOGIN
)
) {
// Change the state to login after this packet has been sent
// so we can send the LoginStartPacket
connection.state = MinecraftProtocol.LOGIN
// Send the login start packet with our desired username
// which the server should use when in game.
connection.send(ClientLoginStartPacket("Example"))
}
}
override fun received(connection: NettyConnection, packet: Packet) {
when (packet) {
// After the login success packet has been read, we know that
// the client has been successfully authenticated with the server and
// should begin reading PLAY packets.
is ServerLoginSuccessPacket -> connection.state = MinecraftProtocol.PLAY
}
}
override fun exception(connection: NettyConnection, cause: Throwable) {
// For any exceptions that we encounter, log them to
// the console so they can be debugged
cause.printStackTrace()
}
}
The following flow assumes that C
represents the client and S
represents the server.
Therefore, C->S
means a packet has been sent from the client to the server.
-
[C->S] Handshake
The client sends a handshake packet to the server, switching the state to login. -
[C->S] Login Start
The client sends a login start packet with the desired username, telling the server it is ready to login. -
Online mode authentication (Optional)
-
[S->C] Encryption Request
The server requests an generated public key, secret key and verify token from the client. It is expected that the client sends a request to Mojang with their access token and a generated Server ID hash. After sending this packet, encryption should be enabled using the generated secret key. -
[C->S] Encryption Response
The client sends an encryption response packet to the server with the public key, secret and verify token.
-
-
[S->C] Login Success
The server will respond with a login success packet if the authentication was successful and immediately switch to thePLAY
state. The client should also switch intoPLAY
.
This wiki will be updated with further information soon. Keep an eye out! 👀