874b6f20c2
Основа — Horizon (MIT). История апстрима не переносится: этот репозиторий ведёт свою.
77 lines
3.1 KiB
Python
77 lines
3.1 KiB
Python
#!/usr/bin/env python3
|
|
"""Generate crates/horizon-protocol/src/ids.rs from the vanilla data generator's
|
|
packets report (`java -DbundlerMainClass=net.minecraft.data.Main -jar server.jar --reports`).
|
|
|
|
Packet ids are protocol facts (the order packets are registered in each
|
|
connection state); the report is the authoritative source for them.
|
|
"""
|
|
|
|
import argparse
|
|
import json
|
|
from pathlib import Path
|
|
|
|
try:
|
|
from . import lab
|
|
except ImportError:
|
|
import lab
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
STATES = ["handshake", "status", "login", "configuration", "play"]
|
|
DIRECTIONS = ["clientbound", "serverbound"]
|
|
|
|
|
|
def const_name(name):
|
|
return name.split(":", 1)[1].replace("/", "_").upper()
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument("--report", type=Path, default=ROOT / ".local/datagen/out/reports/packets.json")
|
|
parser.add_argument("--out", type=Path, default=ROOT / "crates/horizon-protocol/src/ids.rs")
|
|
args = parser.parse_args()
|
|
report = json.loads(args.report.read_text())
|
|
info = lab.version_info()
|
|
lines = [
|
|
f"//! Packet ids per connection state and direction for protocol {info['protocol_version']} ({info['name']}).",
|
|
"//! Generated by tools/generate_packet_ids.py from the data generator's",
|
|
"//! packets report; do not edit by hand.",
|
|
"#![allow(missing_docs)]",
|
|
"use crate::{Direction, State};",
|
|
"",
|
|
]
|
|
tables = []
|
|
for state in STATES:
|
|
lines.append(f"pub mod {state} {{")
|
|
for direction in DIRECTIONS:
|
|
packets = report.get(state, {}).get(direction, {})
|
|
if not packets:
|
|
continue
|
|
ordered = sorted(packets.items(), key=lambda kv: kv[1]["protocol_id"])
|
|
assert [e["protocol_id"] for _, e in ordered] == list(range(len(ordered))), (state, direction)
|
|
lines.append(f" pub mod {direction} {{")
|
|
for name, entry in ordered:
|
|
lines.append(f" pub const {const_name(name)}: i32 = {entry['protocol_id']};")
|
|
lines.append(" /// Packet names indexed by id.")
|
|
names = ", ".join(f'"{name.split(":", 1)[1]}"' for name, _ in ordered)
|
|
lines.append(f" pub const NAMES: &[&str] = &[{names}];")
|
|
lines.append(" }")
|
|
tables.append((state, direction))
|
|
lines.append("}")
|
|
lines.append("")
|
|
lines.append("/// The packet name for an id, if the state and direction define it.")
|
|
lines.append("pub fn name(state: State, direction: Direction, id: i32) -> Option<&'static str> {")
|
|
lines.append(" let names: &[&str] = match (state, direction) {")
|
|
for state, direction in tables:
|
|
lines.append(
|
|
f" (State::{state.capitalize()}, Direction::{direction.capitalize()}) => {state}::{direction}::NAMES,"
|
|
)
|
|
lines.append(" _ => &[],")
|
|
lines.append(" };")
|
|
lines.append(" usize::try_from(id).ok().and_then(|i| names.get(i)).copied()")
|
|
lines.append("}")
|
|
args.out.write_text("\n".join(lines) + "\n")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|