added very basic protocol compiler
This commit is contained in:
parent
16c75882f1
commit
c08f3b5153
1 changed files with 78 additions and 0 deletions
78
aiocraft/minecraft/compiler.py
Executable file
78
aiocraft/minecraft/compiler.py
Executable file
|
@ -0,0 +1,78 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
|
||||||
|
from typing import List, Dict
|
||||||
|
|
||||||
|
DIR_MAP = {"toClient": "clientbound", "toServer": "serverbound"}
|
||||||
|
PREFACE = """\"\"\"[!] This file is autogenerated\"\"\"\n\n"""
|
||||||
|
IMPORTS = """from .minecraft.packet import Packet\nfrom .minecraft.types import *\n"""
|
||||||
|
IMPORT_ALL = """from .* import * # TODO!\n"""
|
||||||
|
OBJECT = """
|
||||||
|
class {name}(Packet):
|
||||||
|
ID : int = 0x{id:X}
|
||||||
|
SLOTS : list = (
|
||||||
|
{slots}
|
||||||
|
)
|
||||||
|
"""
|
||||||
|
|
||||||
|
def snake_to_camel(name:str) -> str:
|
||||||
|
return "".join(x.capitalize() for x in name.split("_"))
|
||||||
|
|
||||||
|
def parse_slot(slot: dict) -> str:
|
||||||
|
if "name" in slot:
|
||||||
|
if "type" in slot and isinstance(slot["type"], str):
|
||||||
|
return f"(\"{slot['name']}\", {slot['type']})"
|
||||||
|
else:
|
||||||
|
return f"(\"{slot['name']}\", [Special])"
|
||||||
|
elif "anon" in slot:
|
||||||
|
if "type" in slot and isinstance(slot["type"], str):
|
||||||
|
return f"(\"anon\", {slot['type']})"
|
||||||
|
else:
|
||||||
|
return f"(\"anon\", [Special])"
|
||||||
|
|
||||||
|
|
||||||
|
class PacketClassWriter:
|
||||||
|
pid : int
|
||||||
|
title : str
|
||||||
|
slots : List[Dict[str, str]]
|
||||||
|
|
||||||
|
def __init__(self, pid:int, title:str, slots:List[Dict[str, str]]):
|
||||||
|
self.pid = pid
|
||||||
|
self.title = title
|
||||||
|
self.slots = slots
|
||||||
|
|
||||||
|
def compile(self) -> str:
|
||||||
|
return PREFACE + IMPORTS + OBJECT.format(id=pid, name=self.title, slots=parse_slot(self.slots))
|
||||||
|
|
||||||
|
def _make_module(path:str):
|
||||||
|
os.mkdir(path)
|
||||||
|
if not path.endswith("/"):
|
||||||
|
path += "/"
|
||||||
|
with open(path + "__init__.py", "w") as f:
|
||||||
|
f.write(PREFACE + IMPORT_ALL)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# TODO load relatively!
|
||||||
|
# with open("???/minecraft-data/data/pc/1.12.2/protocol.json") as f:
|
||||||
|
# data = json.load(f)
|
||||||
|
|
||||||
|
_make_module("protocol")
|
||||||
|
for state in ("handshaking", "status", "login", "play"):
|
||||||
|
_make_module(f"protocol/{state}")
|
||||||
|
for _direction in ("toClient", "toServer"):
|
||||||
|
direction = DIR_MAP[_direction]
|
||||||
|
_make_module(f"protocol/{state}/{direction}")
|
||||||
|
buf = data[state][_direction]["types"]["packet"][1][0]["type"][1]["mappings"]
|
||||||
|
registry = { f"packet_{value}" : int(key, 16) for (key, value) in buf.items() }
|
||||||
|
for p_name in data[state][_direction]["types"].keys():
|
||||||
|
if p_name == "packet":
|
||||||
|
continue # it's the registry entry
|
||||||
|
packet = data[state][_direction]["types"][p_name]
|
||||||
|
pid = registry[p_name]
|
||||||
|
class_name = snake_to_camel(p_name)
|
||||||
|
with open(f"protocol/{state}/{direction}/{p_name}.py", "w") as f:
|
||||||
|
f.write(PacketClassWriter(pid, class_name, packet[1]).compile())
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue