watch_sourid_live.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. #!/usr/bin/env python3
  2. """watch_sourid_live.py — 实时监视 pcap/jsonl 抓包, 解出全部地图 sourid。
  3. 用法(等待用户进图时后台跑):
  4. sudo protocol_bot/.venv/bin/python protocol_bot/scripts/watch_sourid_live.py \
  5. --out /tmp/cap_wugong.jsonl
  6. 边抓边解: 每 2s 扫描新增行, SC-1 批量帧 zlib 解压 → SC51/SC634 decode6
  7. → 打印新发现的 MapName→sourid。Ctrl-C 结束。
  8. """
  9. from __future__ import annotations
  10. import json
  11. import sys
  12. import time
  13. import zlib
  14. sys.path.insert(0, "protocol_bot/src")
  15. from pbot.codec.bitbuf import decode6 # noqa: E402
  16. from pbot.codec.frame import FrameSplitter # noqa: E402
  17. def scan_file(path: str, seen: dict[str, dict]) -> None:
  18. try:
  19. with open(path, encoding="utf-8", errors="replace") as f:
  20. for line in f:
  21. if '"msg": -1' not in line and '"msg": 51' not in line \
  22. and '"msg": 634' not in line:
  23. continue
  24. try:
  25. rec = json.loads(line)
  26. except ValueError:
  27. continue
  28. msg, bh = rec.get("msg"), rec.get("body_hex", "")
  29. if msg not in (-1, 51, 634) or not bh:
  30. continue
  31. def handle(m: int, b: bytes) -> None:
  32. if m == -1:
  33. try:
  34. raw = zlib.decompress(b)
  35. except zlib.error:
  36. return
  37. for f2 in FrameSplitter().feed(raw):
  38. handle(f2.msg_id, f2.body)
  39. return
  40. if m not in (51, 634):
  41. return
  42. try:
  43. text = decode6(b).decode("utf-8", errors="replace")
  44. s = text.find("{")
  45. if s < 0:
  46. return
  47. j = json.loads(text[s:text.rfind("}") + 1])
  48. name = str(j.get("MapName") or j.get("MapId") or "?")
  49. if name in seen and seen[name].get("_m") == "SC51":
  50. return
  51. j["_m"] = f"SC{m}"
  52. seen[name] = j
  53. except Exception:
  54. pass
  55. handle(msg, bytes.fromhex(bh))
  56. except OSError:
  57. pass
  58. def main() -> int:
  59. out = "/tmp/cap_wugong.jsonl"
  60. if "--out" in sys.argv:
  61. out = sys.argv[sys.argv.index("--out") + 1]
  62. print(f"监视 {out} — 等待 SC51/SC634 地图属性帧(Ctrl-C 结束)")
  63. print(f"{'时间':<9} {'显示名':<14} {'MapId':<14} {'sourid':<8} Minimap")
  64. print("-" * 68)
  65. seen: dict[str, dict] = {}
  66. try:
  67. while True:
  68. scan_file(out, seen)
  69. time.sleep(2)
  70. except KeyboardInterrupt:
  71. print("\n==== 最终结果 ====")
  72. for name in sorted(seen):
  73. j = seen[name]
  74. print(f"{name:<14} MapId={j.get('MapId','')} "
  75. f"sourid={j.get('sourid','')} Minimap={j.get('Minimap','')} {j['_m']}")
  76. return 0
  77. if __name__ == "__main__":
  78. sys.exit(main())