diag_5012_monster_probe.py 3.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. #!/usr/bin/env python3
  2. """diag_5012_monster_probe.py — CS5012 小地图怪物请求探针.
  3. 目的: 验证本服 CS5012(body=协议图名)→SC5012 响应格式(全图怪坐标 JSON).
  4. 背景: 本服不下发怪物 SC10, 静止怪对协议端不可见(SC11 只广播移动怪) —
  5. 客户端 MiniMapProxy:RequestMonsters 是合法主动查询通道.
  6. 用法: uv run python scripts/diag_5012_monster_probe.py -u longwu988 \
  7. -p Longwu1988 --zone 14570166 --name 新角色 [--seconds 60]
  8. """
  9. from __future__ import annotations
  10. import argparse
  11. import logging
  12. import sys
  13. import time
  14. sys.path.insert(0, "scripts")
  15. from run_juece13_mine_farthest import ( # noqa: E402
  16. MINE_MAP, MineEnterBehavior, setup_logging, banner,
  17. )
  18. from run_juece13_wugong_autofight import AutoFightBehavior # noqa: E402
  19. import requests
  20. from pbot.bot.runner import pump, run
  21. from pbot.config import Account
  22. from pbot.errors import PbotError
  23. from pbot.game.messages import protocol_map_name
  24. from pbot.game.session import enter_world
  25. from pbot.login.box_client import enter_game_client, login
  26. from pbot.transport.gateway import login_gate_with_retry
  27. from pbot.types import ZoneId
  28. _LOG = logging.getLogger("probe5012")
  29. def main() -> int:
  30. ap = argparse.ArgumentParser()
  31. _ = ap.add_argument("-u", "--user", required=True)
  32. _ = ap.add_argument("-p", "--password", required=True)
  33. _ = ap.add_argument("--zone", type=int, required=True)
  34. _ = ap.add_argument("--name", required=True)
  35. _ = ap.add_argument("--seconds", type=float, default=60.0)
  36. a = ap.parse_args()
  37. setup_logging()
  38. banner("[0] 5012 怪物雷达探针: 区=%d 角色=%s", a.zone, a.name)
  39. http = requests.Session()
  40. http.trust_env = False
  41. http.verify = False
  42. jwt, uid = login(Account(username=a.user, password=a.password))
  43. _ = enter_game_client(http, jwt, ZoneId(a.zone))
  44. key32, sid, real_name, ticket_key, game_port = login_gate_with_retry(
  45. ZoneId(a.zone), jwt, uid, a.name, (8021, 8061, 8001, 8041))
  46. stop: list[bool] = [False]
  47. conn, world, updater = enter_world(ZoneId(a.zone), real_name, ticket_key,
  48. sid, game_port, uid, stop=stop)
  49. _LOG.info("[✓] 出生 map=%s @(%d,%d) uid=%s", world.me.map_name,
  50. world.me.x, world.me.y, world.me.uid)
  51. try:
  52. if world.me.map_name != MINE_MAP:
  53. banner("[1] 传送比奇矿区")
  54. bh = MineEnterBehavior(sid=sid, kill_target=0)
  55. r = run(conn, world, updater, bh, duration_s=300.0)
  56. if world.me.map_name != MINE_MAP:
  57. _LOG.error("[✗] 传送失败 result=%s", r.value)
  58. return 1
  59. time.sleep(3.0)
  60. _ = pump(conn, world, updater, 2.0)
  61. mn = protocol_map_name(world.me.map_id, world.me.map_name)
  62. _LOG.info("[发送] CS5012 body=%r", mn)
  63. _ = conn.send_frame(5012, 0, 0, 0, 0, mn.encode())
  64. deadline = time.time() + a.seconds
  65. n5012 = 0
  66. while time.time() < deadline:
  67. frames = pump(conn, world, updater, 0.5)
  68. for f in frames:
  69. if f.msg_id == 5012:
  70. n5012 += 1
  71. _LOG.info("[SC5012] recog=%d p1=%d p2=%d body=%r",
  72. f.recog, f.p1, f.p2, f.body[:400])
  73. _LOG.info("[结束] 5012 响应 %d 帧", n5012)
  74. return 0 if n5012 else 1
  75. finally:
  76. stop[0] = True
  77. conn.close()
  78. _LOG.info("连接已关闭")
  79. if __name__ == "__main__":
  80. try:
  81. sys.exit(main())
  82. except PbotError as e:
  83. _LOG.error("失败: %s", e.detail)
  84. sys.exit(1)