docs v1.0-LATEST

latest revision of documentation

For basic protocol structure knowledge visit wiki.vg/Protocol_FAQ

Well, now you know about packets, how it represented in cubelib?

Base definitions

  • L2 Packet -> Structure we got after reading packet from network. Could be compressed or not. All that we know about it - its id, it was compressed or not and state when we received it. All L2 packets represented in cubelib with class cubelib.p.Packet

  • L3 Packet -> Structure we got after resolving L2 packet into abstract class. What we know about it depends on what type of packet we have a deal with. All packets have its own structure.

  • State -> One of the protocol states. Handshaking, Status, Login, Play. Available at enum: cubelib.state

  • Bound -> Packet direction. ServerBound = From client To server. ClientBound = From server To client.

  • Compression Threshold -> Min L3 packet length when L2 packet containing it must be compressed. Set by server in ClientBound.Login.SetCompression

  • Packet names in cubelib. All supported packets in cubelib available in library at paths like this: cubelib.p.proto.Bound.State.PacketName

Basic communication example

import cubelib
import socket
import time
import json

connection_timeout = 1 # 1 second

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.SOL_TCP)
server.settimeout(connection_timeout)
server.connect(("localhost", 25565))

# Define base connection params
protocol = cubelib.proto # v-ind
state = cubelib.state.Handshaking
bound = cubelib.bound.Client
compression_threshold = -1 # disabled

# Handshaking
packet = cubelib.proto.ServerBound.Handshaking.Handshake(47, "localhost", 25565, cubelib.state.Status)
# in most of new IDEs you can inspect packet structure by going to the definition (Vscode: F12)
server.sendall(packet.build(compression_threshold))

# Handshake changing protocol state to Status
state = cubelib.state.Status

# Status
packet = cubelib.proto.ServerBound.Status.Request()
server.sendall(packet.build(compression_threshold))

# Reading response
received_packets = [] # creating empty list to store incoming packets

receive_begin = time.time()
receive_buff = bytes()

# receive one packet
while time.time() - receive_begin < connection_timeout:
    receive_buff += server.recv(70_000) # receiving some bytes
    unclaimed = cubelib.readPacketsStream(receive_buff, compression_threshold, bound, received_packets)
    # if byte stream is truncated received packets will be empty and unclaimed data stored in unclaimed

    if received_packets:
        break

if len(received_packets) != 1: # checking for unexcepted behaviour    
    raise RuntimeError("Unexcepted behaviour from the server!")

# Resolving
received_packets = [p.resolve(state, protocol) for p in received_packets]

if received_packets[0].__class__ != cubelib.proto.ClientBound.Status.Response:    
    raise RuntimeError("Unexcepted behaviour from server! Awaited Status.Response, got", received_packets[0].__class__)

response = json.loads(received_packets[0].JsonRsp)
print(response["description"]) # A Minecraft Server

Conclusion

Now, you know how to read and build packets.

A most parts of cubelib are annotated and docstringed, use your IDE to jump through sources of library and inspect structures of packets you need.

Good luck, have fun =]

Last updated