| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990 |
- #!/usr/bin/env python3
- """watch_sourid_live.py — 实时监视 pcap/jsonl 抓包, 解出全部地图 sourid。
- 用法(等待用户进图时后台跑):
- sudo protocol_bot/.venv/bin/python protocol_bot/scripts/watch_sourid_live.py \
- --out /tmp/cap_wugong.jsonl
- 边抓边解: 每 2s 扫描新增行, SC-1 批量帧 zlib 解压 → SC51/SC634 decode6
- → 打印新发现的 MapName→sourid。Ctrl-C 结束。
- """
- from __future__ import annotations
- import json
- import sys
- import time
- import zlib
- sys.path.insert(0, "protocol_bot/src")
- from pbot.codec.bitbuf import decode6 # noqa: E402
- from pbot.codec.frame import FrameSplitter # noqa: E402
- def scan_file(path: str, seen: dict[str, dict]) -> None:
- try:
- with open(path, encoding="utf-8", errors="replace") as f:
- for line in f:
- if '"msg": -1' not in line and '"msg": 51' not in line \
- and '"msg": 634' not in line:
- continue
- try:
- rec = json.loads(line)
- except ValueError:
- continue
- msg, bh = rec.get("msg"), rec.get("body_hex", "")
- if msg not in (-1, 51, 634) or not bh:
- continue
- def handle(m: int, b: bytes) -> None:
- if m == -1:
- try:
- raw = zlib.decompress(b)
- except zlib.error:
- return
- for f2 in FrameSplitter().feed(raw):
- handle(f2.msg_id, f2.body)
- return
- if m not in (51, 634):
- return
- try:
- text = decode6(b).decode("utf-8", errors="replace")
- s = text.find("{")
- if s < 0:
- return
- j = json.loads(text[s:text.rfind("}") + 1])
- name = str(j.get("MapName") or j.get("MapId") or "?")
- if name in seen and seen[name].get("_m") == "SC51":
- return
- j["_m"] = f"SC{m}"
- seen[name] = j
- except Exception:
- pass
- handle(msg, bytes.fromhex(bh))
- except OSError:
- pass
- def main() -> int:
- out = "/tmp/cap_wugong.jsonl"
- if "--out" in sys.argv:
- out = sys.argv[sys.argv.index("--out") + 1]
- print(f"监视 {out} — 等待 SC51/SC634 地图属性帧(Ctrl-C 结束)")
- print(f"{'时间':<9} {'显示名':<14} {'MapId':<14} {'sourid':<8} Minimap")
- print("-" * 68)
- seen: dict[str, dict] = {}
- try:
- while True:
- scan_file(out, seen)
- time.sleep(2)
- except KeyboardInterrupt:
- print("\n==== 最终结果 ====")
- for name in sorted(seen):
- j = seen[name]
- print(f"{name:<14} MapId={j.get('MapId','')} "
- f"sourid={j.get('sourid','')} Minimap={j.get('Minimap','')} {j['_m']}")
- return 0
- if __name__ == "__main__":
- sys.exit(main())
|