fix(go): repair migration wire contracts and runtime lifecycle; document incomplete port
This commit is contained in:
1 parent
e43a310617
commit
32e47014b5
35 files changed
+16826
-438
No files matched your search
Vendored
+52
@@ -0,0 +1,52 @@
|
||||
"""List known incomplete migration artifacts; --check fails until they are ported.
|
||||
|
||||
This is a conservative static inventory, not a claim of gameplay compatibility.
|
||||
"""
|
||||
import argparse
|
||||
import json
|
||||
from pathlib import Path
|
||||
import re
|
||||
import subprocess
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--check", action="store_true")
|
||||
args = parser.parse_args()
|
||||
root = Path(__file__).resolve().parents[2]
|
||||
ids = json.loads((root / "pkg/protocol/testdata/legacy_method_ids.json").read_text(encoding="utf-8"))
|
||||
deps = set(subprocess.check_output(
|
||||
["go", "list", "-deps", "./cmd/ananta-server"], cwd=root).decode().splitlines())
|
||||
stubs, missing_tables, unknown_calls = [], [], []
|
||||
for base in ("internal", "pkg"):
|
||||
for path in sorted((root / base).rglob("*.go")):
|
||||
if path.name.endswith("_test.go"):
|
||||
continue
|
||||
text = path.read_text(encoding="utf-8-sig")
|
||||
rel = path.relative_to(root).as_posix()
|
||||
names = re.findall(r"// (?:Router implementation for|Catalog helper) (\w+)", text)
|
||||
if names:
|
||||
stubs.append({"file": rel, "count": len(names), "functions": names})
|
||||
for filename in re.findall(r'filepath.Join\(configDir, "([^"]+)"\)', text):
|
||||
if not (root / "data/client_data/Configs" / filename).exists():
|
||||
missing_tables.append({"file": rel, "table": filename})
|
||||
# Only inspect the active server, not the unused generated skeletons.
|
||||
if rel.startswith("internal/gameserver/") and "/routers/" not in rel:
|
||||
for name in re.findall(r'MethodGetMethodIDDefault\("([^"]+)"', text):
|
||||
if name not in ids:
|
||||
unknown_calls.append({"file": rel, "method": name})
|
||||
report = {
|
||||
"baseline": "ca2e80f",
|
||||
"stub_functions": sum(row["count"] for row in stubs),
|
||||
"stub_files": len(stubs),
|
||||
"generated_router_connected_to_main": "ananta-ps/internal/gameserver/routers" in deps,
|
||||
"catalogs_connected_to_main": "ananta-ps/internal/catalogs" in deps,
|
||||
"stubs": stubs,
|
||||
"missing_catalog_inputs": missing_tables,
|
||||
"unverified_notification_names": unknown_calls,
|
||||
}
|
||||
out = root / "docs/GO_MIGRATION_INVENTORY.json"
|
||||
out.write_text(json.dumps(report, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
|
||||
print(f"{report['stub_functions']} stub functions in {len(stubs)} files; "
|
||||
f"{len(missing_tables)} missing catalog inputs; {len(unknown_calls)} unverified notifications")
|
||||
print(f"Inventory: {out.relative_to(root)}")
|
||||
if args.check and (stubs or missing_tables or unknown_calls):
|
||||
raise SystemExit(1)
|
||||
Vendored
+44
@@ -0,0 +1,44 @@
|
||||
"""Recover wire metadata from the last C# revision, without transpiling method bodies.
|
||||
|
||||
Run from the repository root: python tools/migration/generate_protocol.py
|
||||
"""
|
||||
import json
|
||||
from pathlib import Path
|
||||
import re
|
||||
import subprocess
|
||||
|
||||
BASE = "ca2e80f"
|
||||
PREFIX = "Ananta.Server/Ananta.Core/Protocol/Client4229938/"
|
||||
|
||||
|
||||
def source(name):
|
||||
return subprocess.check_output(["git", "show", f"{BASE}:{PREFIX}{name}"]).decode("utf-8-sig")
|
||||
|
||||
|
||||
ids = {name: int(value) for name, value in re.findall(
|
||||
r"const uint (\w+)\s*=\s*(\d+)", source("MethodId.cs"))}
|
||||
Path("pkg/protocol/testdata/legacy_method_ids.json").write_text(
|
||||
json.dumps(ids, indent=2) + "\n", encoding="utf-8")
|
||||
header = f"// Code generated from {BASE} C# protocol metadata; DO NOT EDIT.\npackage protocol\n\n"
|
||||
names = header + "var canonicalMethodIDs = map[string]uint32{\n"
|
||||
names += "".join(f'{json.dumps(name)}: {value},\n' for name, value in ids.items())
|
||||
names += "}\n"
|
||||
Path("pkg/protocol/method_names_generated.go").write_text(names, encoding="utf-8")
|
||||
|
||||
rows = re.findall(
|
||||
r'case (\d+)u: body = (Array.Empty<byte>\(\)|\[[^\]]*\]); shape = "([^"]*)"; return true;',
|
||||
source("DefaultReturnCatalog4229938.cs"))
|
||||
assert len(rows) == 2356, "C# return catalog changed; review before generating"
|
||||
out = [header, "var defaultReturnBodies = map[uint32]string{"]
|
||||
for mid, body, shape in rows:
|
||||
data = b"" if body.startswith("Array") else bytes(
|
||||
int(value.strip(), 16) for value in body[1:-1].split(",") if value.strip())
|
||||
encoded = "".join(f"\\x{value:02x}" for value in data)
|
||||
out.append(f'{mid}: "{encoded}", // {shape}')
|
||||
out += ["}", "", "// DefaultReturnBody returns an independent payload for the client return reader.",
|
||||
"func DefaultReturnBody(methodID uint32) ([]byte, bool) {",
|
||||
"body, ok := defaultReturnBodies[methodID]", "return []byte(body), ok", "}"]
|
||||
Path("pkg/protocol/default_returns_generated.go").write_text("\n".join(out) + "\n", encoding="utf-8")
|
||||
subprocess.run(["gofmt", "-w", "pkg/protocol/default_returns_generated.go",
|
||||
"pkg/protocol/method_names_generated.go"], check=True)
|
||||
print(f"Recovered {len(ids)} names and {len(rows)} return contracts from {BASE}")
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
[
|
||||
"SyncPlayerPositionAndFacing",
|
||||
"AskMoveStart",
|
||||
"AskMoveStop",
|
||||
"AskUpdatePlayerPosition",
|
||||
"AskPreSwitchSpirit",
|
||||
"AskTeleportToScene",
|
||||
"SwitchSceneDirect",
|
||||
"AskDriveVehicle",
|
||||
"AskExitVehicle",
|
||||
"SyncPlayerVehicleInfo",
|
||||
"SyncAetherVehicleInit",
|
||||
"AskSetWantedLevel",
|
||||
"AskPoliceArrest",
|
||||
"ReportPoliceArrestFinish",
|
||||
"AskPayFine",
|
||||
"AskReleaseFromPrison",
|
||||
"AskSetCrowdDensity",
|
||||
"AskPlayerAttack",
|
||||
"AskPlayerCastSkill",
|
||||
"AskUnlockFightStyle",
|
||||
"SyncChangeSpirit",
|
||||
"AskChineseChessMove",
|
||||
"AskMahjongAction"
|
||||
]
|
||||
Reference in new issue
Block a user