Compare commits
5 Commits
master
...
json-packe
Author | SHA1 | Date |
---|---|---|
|
134ca1eb89 | |
|
191b17fcc1 | |
|
7acce26ec5 | |
|
a9aff18c94 | |
|
8e76e96373 |
80
README.md
80
README.md
|
@ -1,80 +0,0 @@
|
||||||
## Supported packets
|
|
||||||
|
|
||||||
| ID | Packet name | Ready |
|
|
||||||
|-----|----------------------------------|-------|
|
|
||||||
| 000 | Packet0KeepAlive | Yes |
|
|
||||||
| 001 | Packet1Login | Yes |
|
|
||||||
| 002 | Packet2Handshake | Yes |
|
|
||||||
| 003 | Packet3Chat | Yes |
|
|
||||||
| 004 | Packet4UpdateTime | Yes |
|
|
||||||
| 005 | Packet5PlayerInventory | Yes |
|
|
||||||
| 006 | Packet6SpawnPosition | Yes |
|
|
||||||
| 007 | Packet7UseEntity | Yes |
|
|
||||||
| 008 | Packet8UpdateHealth | Yes |
|
|
||||||
| 009 | Packet9Respawn | Yes |
|
|
||||||
| 010 | Packet10Flying | Yes |
|
|
||||||
| 011 | Packet11PlayerPosition | Yes |
|
|
||||||
| 012 | Packet12PlayerLook | Yes |
|
|
||||||
| 013 | Packet13PlayerLookMove | Yes |
|
|
||||||
| 014 | Packet14BlockDig | Yes |
|
|
||||||
| 015 | Packet15Place | Yes |
|
|
||||||
| 016 | Packet16BlockItemSwitch | Yes |
|
|
||||||
| 017 | Packet17Sleep | Yes |
|
|
||||||
| 018 | Packet18Animation | Yes |
|
|
||||||
| 019 | Packet19EntityAction | Yes |
|
|
||||||
| 020 | Packet20NamedEntitySpawn | Yes |
|
|
||||||
| 021 | Packet21PickupSpawn | Yes |
|
|
||||||
| 022 | Packet22Collect | Yes |
|
|
||||||
| 023 | Packet23VehicleSpawn | Yes |
|
|
||||||
| 024 | Packet24MobSpawn | Yes |
|
|
||||||
| 025 | Packet25EntityPainting | Yes |
|
|
||||||
| 027 | Packet27Position | No |
|
|
||||||
| 028 | Packet28EntityVelocity | Yes |
|
|
||||||
| 029 | Packet29DestroyEntity | Yes |
|
|
||||||
| 030 | Packet30Entity | Yes |
|
|
||||||
| 031 | Packet31RelEntityMove | Yes |
|
|
||||||
| 032 | Packet32EntityLook | Yes |
|
|
||||||
| 033 | Packet33RelEntityMoveLook | Yes |
|
|
||||||
| 034 | Packet34EntityTeleport | Yes |
|
|
||||||
| 035 | Packet35EntityNickname | Yes |
|
|
||||||
| 038 | Packet38EntityStatus | Yes |
|
|
||||||
| 039 | Packet39AttachEntity | Yes |
|
|
||||||
| 040 | Packet40EntityMetadata | Yes |
|
|
||||||
| 041 | Packet41EntityPlayerGamemode | Yes |
|
|
||||||
| 050 | Packet50PreChunk | Yes |
|
|
||||||
| 051 | Packet51MapChunk | Yes |
|
|
||||||
| 052 | Packet52MultiBlockChange | Yes |
|
|
||||||
| 053 | Packet53BlockChange | Yes |
|
|
||||||
| 054 | Packet54PlayNoteBlock | Yes |
|
|
||||||
| 056 | Packet56RequestChunk | No |
|
|
||||||
| 060 | Packet60Explosion | Yes |
|
|
||||||
| 061 | Packet61PlaySoundEffect | Yes |
|
|
||||||
| 070 | Packet70Bed | No |
|
|
||||||
| 071 | Packet71Weather | No |
|
|
||||||
| 072 | Packet72UpdatePlayerProfile | Yes |
|
|
||||||
| 073 | Packet73WeatherStatus | Yes |
|
|
||||||
| 100 | Packet100OpenWindow | Yes |
|
|
||||||
| 101 | Packet101CloseWindow | Yes |
|
|
||||||
| 102 | Packet102WindowClick | Yes |
|
|
||||||
| 103 | Packet103SetSlot | Yes |
|
|
||||||
| 104 | Packet104WindowItems | Yes |
|
|
||||||
| 105 | Packet105UpdateProgressbar | Yes |
|
|
||||||
| 106 | Packet106Transaction | Yes |
|
|
||||||
| 107 | Packet107UpdateCreativeInventory | Yes |
|
|
||||||
| 108 | Packet108SetHotbarOffset | Yes |
|
|
||||||
| 130 | Packet130UpdateSign | Yes |
|
|
||||||
| 131 | Packet131MapData | Yes |
|
|
||||||
| 132 | Packet132SetMobSpawner | Yes |
|
|
||||||
| 133 | Packet133OpenGuidebook | Yes |
|
|
||||||
| 134 | Packet134ItemData | Yes |
|
|
||||||
| 135 | Packet135PlacementMode | Yes |
|
|
||||||
| 136 | Packet136SendKey | Yes |
|
|
||||||
| 137 | Packet137UpdateFlag | Yes |
|
|
||||||
| 138 | Packet138PlayerList | Yes |
|
|
||||||
| 139 | Packet139SetPaintingMotive | Yes |
|
|
||||||
| 140 | Packet140TileEntityData | Yes |
|
|
||||||
| 141 | Packet141UpdateFlag | Yes |
|
|
||||||
| 142 | Packet142OpenFlagWindow | Yes |
|
|
||||||
| 143 | Packet143PhotoMode | Yes |
|
|
||||||
| 200 | Packet200Statistic | Yes |
|
|
||||||
| 255 | Packet255KickDisconnect | Yes |
|
|
|
@ -0,0 +1,294 @@
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"protocol_version": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"game_version": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"packets": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"server": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"client": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"fields": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/field"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id",
|
||||||
|
"name"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"definitions": {
|
||||||
|
"type": {
|
||||||
|
"type": "object",
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"bool",
|
||||||
|
"byte",
|
||||||
|
"ubyte",
|
||||||
|
"short",
|
||||||
|
"ushort",
|
||||||
|
"int",
|
||||||
|
"uint",
|
||||||
|
"long",
|
||||||
|
"ulong",
|
||||||
|
"float",
|
||||||
|
"double",
|
||||||
|
"itemstack",
|
||||||
|
"optional_itemstack",
|
||||||
|
"itemstack_nbt",
|
||||||
|
"optional_itemstack_nbt",
|
||||||
|
"compoundtag",
|
||||||
|
"synchedentitydata"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"const": "list"
|
||||||
|
},
|
||||||
|
"item": {
|
||||||
|
"$ref": "#/definitions/type"
|
||||||
|
},
|
||||||
|
"size": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"sizetype": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"maxsize": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"item"
|
||||||
|
],
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"required": [
|
||||||
|
"size"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"required": [
|
||||||
|
"sizetype",
|
||||||
|
"maxsize"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"const": "column_major_list"
|
||||||
|
},
|
||||||
|
"fields": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/field"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"size": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"sizetype": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"maxsize": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"fields"
|
||||||
|
],
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"required": [
|
||||||
|
"size"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"required": [
|
||||||
|
"sizetype",
|
||||||
|
"maxsize"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"string",
|
||||||
|
"utfstring"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"maxsize": {
|
||||||
|
"type": "number"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"maxsize"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"const": "bytes"
|
||||||
|
},
|
||||||
|
"size": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"sizetype": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"ubyte",
|
||||||
|
"byte",
|
||||||
|
"ushort",
|
||||||
|
"short",
|
||||||
|
"uint",
|
||||||
|
"int"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"maxsize": {
|
||||||
|
"type": "number"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"required": [
|
||||||
|
"size"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"required": [
|
||||||
|
"sizetype",
|
||||||
|
"maxsize"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"const": "bytes_compressed"
|
||||||
|
},
|
||||||
|
"sizetype": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"ubyte",
|
||||||
|
"byte",
|
||||||
|
"ushort",
|
||||||
|
"short",
|
||||||
|
"uint",
|
||||||
|
"int"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"maxsize": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"method": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"zlib",
|
||||||
|
"gzip"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"method",
|
||||||
|
"maxsize",
|
||||||
|
"sizetype"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"const": "struct"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"fields": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/type"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"if": {
|
||||||
|
"$ref": "#/definitions/condition"
|
||||||
|
},
|
||||||
|
"post": {
|
||||||
|
"type": "array"
|
||||||
|
},
|
||||||
|
"proptype": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"type"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"field": {
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"name"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/type"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"condition": {
|
||||||
|
"type": "array"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"protocol_version",
|
||||||
|
"game_version",
|
||||||
|
"packets"
|
||||||
|
]
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,173 @@
|
||||||
|
from json import load
|
||||||
|
from dataclasses import dataclass, field
|
||||||
|
from typing import Literal, Optional, Union
|
||||||
|
from pprint import pprint
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(slots=True)
|
||||||
|
class Condition:
|
||||||
|
a: Union["Condition", str, int, float]
|
||||||
|
operator: Literal["gt", "lt", "ge", "le", "eq", "and", "or", "xor"]
|
||||||
|
b: Union["Condition", str, int, float]
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(slots=True)
|
||||||
|
class Field:
|
||||||
|
type: Literal[
|
||||||
|
"bool",
|
||||||
|
"byte",
|
||||||
|
"ubyte",
|
||||||
|
"short",
|
||||||
|
"ushort",
|
||||||
|
"int",
|
||||||
|
"uint",
|
||||||
|
"long",
|
||||||
|
"ulong",
|
||||||
|
"float",
|
||||||
|
"double",
|
||||||
|
"itemstack",
|
||||||
|
"optional_itemstack",
|
||||||
|
"itemstack_nbt",
|
||||||
|
"optional_itemstack_nbt",
|
||||||
|
"compoundtag",
|
||||||
|
"synchedentitydata",
|
||||||
|
"list", # AAABBBCCC
|
||||||
|
"column_major_list", # ABCABCABC
|
||||||
|
"string",
|
||||||
|
"utfstring",
|
||||||
|
"bytes",
|
||||||
|
"bytes_compressed",
|
||||||
|
"struct",
|
||||||
|
]
|
||||||
|
|
||||||
|
maxsize: Optional[int] = None
|
||||||
|
size: Optional[int] = None
|
||||||
|
sizetype: Optional[
|
||||||
|
Literal["byte", "ubyte", "short", "ushort", "int", "uint"]
|
||||||
|
] = None
|
||||||
|
condition: Optional[Condition] = None
|
||||||
|
method: Optional[Literal["zlib", "gzip"]] = None
|
||||||
|
fields: Optional[list["NamedField"]] = None
|
||||||
|
item: Optional[Union["Field", "NamedField"]] = None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _add_size(kwargs: dict, data: dict, sizetype: str = "short", maxsize: int = 256) -> dict:
|
||||||
|
if (size := data.get("size")) is not None:
|
||||||
|
kwargs['size'] = size
|
||||||
|
else:
|
||||||
|
kwargs['sizetype'] = data.get("sizetype", sizetype)
|
||||||
|
kwargs['maxsize'] = int(data.get("maxsize", maxsize))
|
||||||
|
return kwargs
|
||||||
|
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _get_init_args(cls, data: dict) -> tuple[tuple, dict]:
|
||||||
|
args = (data['type'],)
|
||||||
|
kwargs = {}
|
||||||
|
kwargs['condition'] = data.get("condition")
|
||||||
|
|
||||||
|
match data["type"]:
|
||||||
|
case "bool":
|
||||||
|
pass
|
||||||
|
case "byte" | "ubyte":
|
||||||
|
pass
|
||||||
|
case "short" | "ushort":
|
||||||
|
pass
|
||||||
|
case "int" | "uint":
|
||||||
|
pass
|
||||||
|
case "long" | "ulong":
|
||||||
|
pass
|
||||||
|
case "float":
|
||||||
|
pass
|
||||||
|
case "double":
|
||||||
|
pass
|
||||||
|
case "string" | "utfstring" | "bytes":
|
||||||
|
kwargs = cls._add_size(kwargs, data)
|
||||||
|
case "bytes_compressed":
|
||||||
|
kwargs['method'] = data.get("method")
|
||||||
|
assert kwargs['method'] in ("gzip", "zlib")
|
||||||
|
kwargs = cls._add_size(kwargs, data, maxsize=16777216)
|
||||||
|
case "list":
|
||||||
|
kwargs = cls._add_size(kwargs, data, maxsize=1024)
|
||||||
|
kwargs['item'] = data.get("item")
|
||||||
|
raise NotImplementedError(f"can't do list yet")
|
||||||
|
case "column_major_list":
|
||||||
|
kwargs = cls._add_size(kwargs, data)
|
||||||
|
kwargs['fields'] = list(map(NamedField.fromdict, data["fields"]))
|
||||||
|
case "optional_itemstack":
|
||||||
|
print("TODO: optional_itemstack")
|
||||||
|
case "optional_itemstack_nbt":
|
||||||
|
print("TODO: optional_itemstack_nbt")
|
||||||
|
case "itemstack":
|
||||||
|
print("TODO: itemstack")
|
||||||
|
case "itemstack_nbt":
|
||||||
|
print("TODO: itemstack_nbt")
|
||||||
|
case "synchedentitydata":
|
||||||
|
print("TODO: synchedentitydata")
|
||||||
|
case "compoundtag":
|
||||||
|
print("TODO: compoundtag")
|
||||||
|
case name:
|
||||||
|
raise NotImplementedError(f"unknown field type {name}")
|
||||||
|
return args, kwargs
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def fromdict(cls, data: dict) -> "Field":
|
||||||
|
args, kwargs = cls._get_init_args(data)
|
||||||
|
return cls(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(slots=True)
|
||||||
|
class NamedField(Field):
|
||||||
|
name: str = ""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _get_init_args(cls, data: dict) -> tuple[tuple, dict]:
|
||||||
|
args, kwargs = Field._get_init_args(data)
|
||||||
|
kwargs['name'] = data['name']
|
||||||
|
return args, kwargs
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def fromdict(cls, data: dict) -> "NamedField":
|
||||||
|
args, kwargs = cls._get_init_args(data)
|
||||||
|
return cls(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(slots=True)
|
||||||
|
class PacketSchema:
|
||||||
|
id: int
|
||||||
|
name: str
|
||||||
|
server: bool = False
|
||||||
|
client: bool = False
|
||||||
|
fields: list[NamedField] = field(default_factory=list)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def fromdict(cls, data: dict) -> "PacketSchema":
|
||||||
|
assert data.get("server", False) or data.get("client", False)
|
||||||
|
return cls(
|
||||||
|
data["id"],
|
||||||
|
data["name"],
|
||||||
|
data.get("server", False),
|
||||||
|
data.get("client", True),
|
||||||
|
list(map(NamedField.fromdict, data["fields"])),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(slots=True)
|
||||||
|
class ProtocolSchema:
|
||||||
|
protocol_version: int
|
||||||
|
game_version: str
|
||||||
|
packets: list[PacketSchema]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def fromdict(cls, data: dict) -> "ProtocolSchema":
|
||||||
|
return cls(
|
||||||
|
protocol_version=data["protocol_version"],
|
||||||
|
game_version=data["game_version"],
|
||||||
|
packets=list(map(PacketSchema.fromdict, data["packets"])),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
with open("../packets.json", "r") as f:
|
||||||
|
data = load(f)
|
||||||
|
|
||||||
|
schema = ProtocolSchema.fromdict(data)
|
Loading…
Reference in New Issue