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