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.PacketL3 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.stateBound -> 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.SetCompressionPacket 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