EasyProtoLib
English
Description
This is a Minecraft protocol library written in Python, with lightweight and ease of use as its primary goals, and high performance within pure Python as a secondary goal. Currently, it only supports MCJE 1.18.2. Due to the author's academic commitments, this library is currently in a semi-hibernation state. Please use it with caution.
Quick Start
Installation
Install this protocol library using pip:
python -m pip install easyprotolib
Build Your First Packet
This protocol library does not provide a network layer abstraction; it is only responsible for protocol construction and parsing.
import easyprotolib as ep # Import EasyProtoLib
packet = ep.MCSHandshake(
ProtocolVersion=ep.MCPVarInt(758), # Set protocol version (758 corresponds to 1.18.2)
ServerAddress=ep.MCPString("127.0.0.1"), # Set server address (not normally validated by vanilla servers)
ServerPort=ep.MCPUnsignedShort(25565), # Set server port
NextState=ep.MCPVarInt(1) # Set next protocol state
)
data = packet.pack() # Serialize the packet, return serialized result
print(data)
# Can use socket.socket().send(data) to send the packet
The field names of a packet can be found in the fields class attribute of the packet class. Each item in fields contains the field name as the first element, the field type as the second, and the default value as the third; if None, it means no default value. Field names are case‑insensitive and ignore spaces, underscores, and hyphens. Therefore, the following code is equivalent to the one above:
import easyprotolib as ep # Import EasyProtoLib
# A more Pythonic style
packet = ep.MCSHandshake(
protocol_version=ep.MCPVarInt(758), # Set protocol version (758 corresponds to 1.18.2)
server_address=ep.MCPString("127.0.0.1"), # Set server address (not normally validated by vanilla servers)
# Server port uses default MCPUnsignedShort(25565)
next_state=ep.MCPVarInt(1) # Set next protocol state
)
data = packet.pack() # Serialize the packet, return serialized result
print(data)
# Can use socket.socket().send(data) to send the packet
Parse a Packet
import easyprotolib as ep
data = b'\x10\x00\xf6\x05\t127.0.0.1c\xdd\x01'
config = ep.MCConfig(ep.STATE_HANDSHAKE, ep.SIDE_SERVER) # Configure yourself; ep.SIDE_SERVER means you are the server side
packet = ep.MCDataPacket.unpack(config, data)
print(f"Packet ID: {packet.packet_id}") # Packet ID: 0
print(f"Packet class: {packet.__class__.__name__}") # Packet class: MCSHandshake
print(f"Packet data: {packet.data}") # Packet data: {'ProtocolVersion': 758, ...}
print(f"Packet length: {packet.length}") # Packet length: 17
print(f"Remaining data: {data[packet.length:]}") # Remaining data: b''
# You can repeatedly call MCDataPacket.deserialization() until it returns None, meaning the remaining data is not enough to form a complete packet.
Custom Packet
import easyprotolib as ep
# Library naming convention: MC + receiving side (C/S) + packet name + (optional) State for disambiguation
class MCSMyDataPacket(ep.MCSPlayDataPacket): # A packet received and processed by the server (MCS) in the Play state
fields = [
# Field name: IntField; Field type: VarInt; Default: None
("IntField", ep.MCPVarInt, None),
# Field name: StringField; Field type: MCPString; Default: ep.MCPString("Hello world")
("StringField", ep.MCPString, ep.MCPString("Hello world"))
]
packet_id = 0xFF # Packet ID: 0xff
# You can then construct or parse this packet just like a native packet, without any additional handling.
Custom Data Types
Custom Atomic Data Type
import easyprotolib as ep
class MCMyObject(ep.MCPObject):
def __init__(self, data: tuple[str, int]):
super().__init__(data) # Automatically registers self.data
def _obj_serialization(self) -> bytearray:
# Implement serialization; do not override serialization()
return ep.MCPString(self.data[0]) + ep.MCPVarInt(
self.data[
1]) # No need to explicitly call MCPObject's serialization; addition automatically serializes
@staticmethod
def _obj_deserialization(data: bytearray) -> tuple[tuple[str, int], int]:
# Implement deserialization (static)
string, offset = ep.MCPString.deserialize(data)
varint, offset2 = ep.MCPVarInt.deserialize(data[offset:])
# Return value: tuple[actual payload, number of bytes processed]
return (string, varint), offset + offset2
# You can then use this data type normally.
Custom Array Type
import easyprotolib as ep
class MCIntArray(ep.MCPObjectArray): # Defines a 1D array of MCPInt
MCObjectType = ep.MCPInt # Specify the element type
# You can then use this array normally.
class MCIntArrayArray(ep.MCPObjectArray): # Defines a 2D array of MCPInt
MCObjectType = MCIntArray # Specify the corresponding 1D array type; similarly for higher dimensions
# You can then use this array normally.
Third‑Party Library Copyright Information
| Name | Version | License |
|---|---|---|
| mutf8 | >=1.0.0 | MIT |
For full details, see THIRD-PARTY.json.
Disclaimer
The authors and contributors of this library are not responsible for any consequences arising from the use of this library. The authors and contributors firmly oppose any illegal activities carried out based on this project, such as attacking servers.
中文
描述
这是一个使用 Python 编写的 Minecraft 协议库,以轻量、易用为主要目标,以在纯Python范围内的高性能为次要目标,目前仅支持MCJE 1.18.2。由于作者学业问题,本库目前处于半停更状态。请谨慎使用本库。
快速开始
安装
使用 pip 安装此协议库:
python -m pip install easyprotolib
构建你的第一个数据包
此协议库没有提供网络层抽象,仅负责协议构建和解析。
import easyprotolib as ep # 导入 EasyProtoLib
packet = ep.MCSHandshake(
ProtocolVersion=ep.MCPVarInt(758), # 设置协议号(758对应1.18.2)
ServerAddress=ep.MCPString("127.0.0.1"), # 设置服务器地址(通常不被原版服务器用于验证)
ServerPort=ep.MCPUnsignedShort(25565), # 设置服务器端口
NextState=ep.MCPVarInt(1) # 设置下一个协议状态
)
data = packet.pack() # 序列化数据包,返回序列化结果
print(data)
# 可使用 socket.socket().send(data) 发送数据包
数据包的字段名可以在数据包类中的 fields 类属性中找到。fields 每一项的第一项是字段名,第二项是字段类型,第三项是默认值,如为 None 则代表无默认值。字段名忽略大小写,忽略空格、下划线和连字符。所以以下代码和以上代码等价:
import easyprotolib as ep # 导入 EasyProtoLib
# 更符合Python编码习惯的写法
packet = ep.MCSHandshake(
protocol_version=ep.MCPVarInt(758), # 设置协议号(758对应1.18.2)
server_address=ep.MCPString("127.0.0.1"), # 设置服务器地址(通常不被原版服务器用于验证)
# 服务器端口使用默认值 MCPUnsignedShort(25565)
next_state=ep.MCPVarInt(1) # 设置下一个协议状态
)
data = packet.pack() # 序列化数据包,返回序列化结果
print(data)
# 可使用 socket.socket().send(data) 发送数据包
解析数据包
import easyprotolib as ep
data = b'\x10\x00\xf6\x05\t127.0.0.1c\xdd\x01'
config = ep.MCConfig(ep.STATE_HANDSHAKE, ep.SIDE_SERVER) # 配置自己, ep.SIDE_SERVER 表示自己是服务端
packet = ep.MCDataPacket.unpack(config, data)
print(f"数据包ID: {packet.packet_id}") # 数据包ID: 0
print(f"数据包类: {packet.__class__.__name__}") # 数据包类: MCSHandshake
print(f"数据包数据: {packet.data}") # 数据包数据: {'ProtocolVersion': 758, ...}
print(f"数据包长度: {packet.length}") # 数据包长度: 17
print(f"下一段数据: {data[packet.length:]}") # 下一段数据: b''
# 可以循环调用MCDataPacket.deserialization(), 直到返回值为None, 则意味着剩余数据凑不出一个完整的数据包
自定义数据包
import easyprotolib as ep
# 库命名约定: MC + 接收端(C/S) + 包名 + 所处的State(可选, 用于消歧义)
class MCSMyDataPacket(ep.MCSPlayDataPacket): # 由服务端(MCS)在Play状态下接收并处理的数据包
fields = [
# 字段名: IntField; 字段类型: VarInt; 默认值: 无
("IntField", ep.MCPVarInt, None),
# 字段名: StringField; 字段类型: MCPString; 默认值: ep.MCPString("Hello world")
("StringField", ep.MCPString, ep.MCPString("Hello world"))
]
packet_id = 0xFF # 数据包ID: 0xff
# 随后可像原生数据包般构建或解析该数据包, 无需其他处理
自定义数据类型
自定义原子数据类型
import easyprotolib as ep
class MCMyObject(ep.MCPObject):
def __init__(self, data: tuple[str, int]):
super().__init__(data) # 自动注册 self.data
def _obj_serialization(self) -> bytearray:
# 编写序列化方法, 请不要重写 serialization() 方法
return ep.MCPString(self.data[0]) + ep.MCPVarInt(
self.data[1]) # 无需显式调用 MCPObject 的序列化方法, 相加时会自动序列化
@staticmethod
def _obj_deserialization(data: bytearray) -> tuple[tuple[str, int], int]:
# 编写反序列化方法(静态)
string, offset = ep.MCPString.deserialize(data)
varint, offset2 = ep.MCPVarInt.deserialize(data[offset:])
# 返回值: tuple[实际负载, 已处理的字节流长度]
return (string, varint), offset + offset2
# 随后可正常使用该数据类型
自定义数组类型
import easyprotolib as ep
class MCIntArray(ep.MCPObjectArray): # 定义一维 MCPInt 数组
MCObjectType = ep.MCPInt # 写上该数组的元素类型
# 随后可正常使用该数组
class MCIntArrayArray(ep.MCPObjectArray): # 定义二维 MCPInt 数组
MCObjectType = MCIntArray # 写上对应的一维数组的类型即可, 多维数组以此类推
# 随后可正常使用该数组
第三方库版权信息
| 名称 | 版本 | 协议 |
|---|---|---|
| mutf8 | >=1.0.0 | MIT |
完整信息参见 THIRD-PARTY.json 。
免责声明
本库的作者和贡献者不对因使用本库而产生的任何后果负责。作者和贡献者坚决反对任何基于本项目实施的非法活动,例如攻击服务器。
Metadata
Release files for easyprotolib 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| easyprotolib-0.2.0.tar.gz | 32.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| easyprotolib-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 62.9 kB
Release files / easyprotolib-0.2.0.tar.gz
| Download URL | easyprotolib-0.2.0.tar.gz |
|---|---|
| Size | 32.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0b74843ec152e3b1eb3827f15a927d0649f0aa02815150d06c61a6da4ddf5ff7
|
|
BLAKE2b-256 checksum How to use checksums |
d675fce47325d0624552f0c42ec90aee44ecb4d85c0aa1c6df0d594a92cc9ae7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.2
|
Release files / easyprotolib-0.2.0-py3-none-any.whl
| Download URL | easyprotolib-0.2.0-py3-none-any.whl |
|---|---|
| Size | 30.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c8de6eff601ddf20a22e97bdbc2fbacb28f17953aa79f66b635fcdedbcd8b7bb
|
|
BLAKE2b-256 checksum How to use checksums |
b8e55494d55659af08f03125b0db95bf4a96494ac8d8239fadb1fe3865675a17
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.2
|