| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- """quest_probe.py — 激活任务态探测: 走位活动 → CS3031 → dump SC643 真实按钮。
- 背景(2026-09-29):
- - 凌风踏雪 CS1010(传送员)/CS1011@act_move,2 全部无响应 — 任务态挂起
- - 用户真客户端弹窗证实: 传送员列表无"地牢一层东"(任务图, 只能走任务按钮)
- → 本脚本: 登录后先走位活动(证明会话健康) → 发 CS3031 → 长窗口收集 SC643
- → dump 弹窗全部按钮 Act(不盲点) → 按用户确认的 Act 传送。
- """
- from __future__ import annotations
- import importlib.util
- import json
- import logging
- import re
- import sys
- import time
- from pathlib import Path
- ROOT = Path(__file__).resolve().parents[2]
- sys.path.insert(0, str(ROOT / "cpp_reversed"))
- sys.path.insert(0, str(ROOT / "protocol_bot" / "src"))
- import requests # noqa: E402
- from pbot.config import Account # noqa: E402
- from pbot.game.session import enter_world # noqa: E402
- from pbot.login.box_client import enter_game_client, login # noqa: E402
- from pbot.transport.gateway import login_gate_with_retry # noqa: E402
- from pbot.world.update import WorldUpdater # noqa: E402
- from map_parser import load as load_map # noqa: E402
- _spec = importlib.util.spec_from_file_location(
- "wt", ROOT / "protocol_bot" / "scripts" / "watch_tp_pathfind.py")
- wt = importlib.util.module_from_spec(_spec)
- sys.modules["wt"] = wt
- _spec.loader.exec_module(wt)
- _LOG = logging.getLogger("quest_probe")
- LINK_RE = re.compile(r"link=@([^|<>]+)")
- def main() -> int:
- http = requests.Session()
- http.trust_env = False
- http.verify = False
- jwt, uid = login(Account(username="longwu988", password="Longwu1988"))
- _ = enter_game_client(http, jwt, 14558825)
- key32, sid, rname, tkey, gport = login_gate_with_retry(
- 14558825, jwt, uid, "凌风踏雪", wt.PORTS)
- stop = [False]
- conn, world, updater = enter_world(14558825, rname, tkey, sid, gport, uid,
- stop=stop)
- _LOG.info("[出生] %s @(%d,%d)", world.me.map_name, world.me.x, world.me.y)
- try:
- time.sleep(8.0)
- wt.pump(conn, world, updater, 1.0)
- # ---- 1. 走位活动: 出墙格 + 走到传送员旁(证明会话健康, 顺便对话) ----
- m3 = load_map(str(ROOT / "protocol_bot" / "assets" / "maps" / "3.map"))
- me = (world.me.x, world.me.y)
- if not m3.get_cell(me[0], me[1]).is_walkable:
- for rr in range(1, 6):
- near = next(((me[0] + dx, me[1] + dy)
- for dx in range(-rr, rr + 1)
- for dy in range(-rr, rr + 1)
- if max(abs(dx), abs(dy)) == rr
- and 0 <= me[0] + dx < m3.width
- and 0 <= me[1] + dy < m3.height
- and m3.get_cell(me[0] + dx,
- me[1] + dy).is_walkable), None)
- if near:
- _ = wt.goto(conn, sid, world, updater, m3, near)
- _LOG.info("[出墙] %s → %s", me, near)
- break
- _ = wt.goto(conn, sid, world, updater, m3, (340, 338))
- _LOG.info("[活动] 走位完成 @(%d,%d)", world.me.x, world.me.y)
- time.sleep(3.0)
- # ---- 2. CS3031 激活任务态 ----
- dialogs: list[dict] = []
- _ = conn.send_frame(
- 3031, 0, 0, 0, sid,
- (ROOT / "protocol_bot" / "assets" / "cs3031_full.bin").read_bytes())
- _LOG.info("[CS3031] 已发, 3s 后发 1011@renwu_mov,1")
- time.sleep(3.0)
- wt.pump(conn, world, updater, 0.5)
- _ = conn.send_frame(
- 1011, 0, 0, 0, sid,
- b'{"UserID":"999999999","Act":"@renwu_mov,1","index":999999999}')
- _LOG.info("[CS1011] @renwu_mov,1 已发 — 长窗口 45s 收弹窗")
- # ---- 2.5 传送员对话(蜈蚣洞穴=地牢一层东, 用户实证) ----
- time.sleep(6.0)
- wt.pump(conn, world, updater, 0.5)
- body = json.dumps({"UserID": wt.TELEPORTER_AID, "index": 2},
- separators=(",", ":")).encode()
- for i in range(3):
- _ = conn.send_frame(1010, 0, 0, 0, sid, body)
- _LOG.info("[传送员] CS1010 第%d次", i + 1)
- t0 = time.time()
- while time.time() - t0 < 5:
- wt.pump(conn, world, updater, 0.2)
- if world.npc_dialog:
- dialogs.append(dict(world.npc_dialog))
- _LOG.info("[传送员弹窗✓] 到达")
- break
- if dialogs:
- break
- time.sleep(2.0)
- # ---- 3. 长窗口收集 SC643 ----
- t0 = time.time()
- while time.time() - t0 < 45:
- for f in conn.recv_frames(0.3):
- pre = world.npc_dialog
- updater.apply(world, f)
- if f.msg_id == 643 and world.npc_dialog and \
- world.npc_dialog is not pre:
- dialogs.append(dict(world.npc_dialog))
- _LOG.info("[SC643 #%d] 到达", len(dialogs))
- if f.msg_id in (634, 800):
- _LOG.info("[传送帧] SC%d — 落地 %s", f.msg_id,
- world.me.map_name)
- if dialogs and time.time() - t0 > 15:
- break
- _LOG.info("[终态] %s @(%d,%d)", world.me.map_name, world.me.x,
- world.me.y)
- if not dialogs:
- _LOG.error("[结论] 45s 无 SC643 — 任务态仍挂起")
- return 1
- for i, d in enumerate(dialogs):
- smsg = str(d.get("sMsg", ""))
- links = LINK_RE.findall(smsg)
- texts = re.findall(r"text=([^|<>]+)", smsg)
- _LOG.info("[弹窗%d] UserID=%s index=%s", i + 1, d.get("UserID"),
- d.get("index"))
- _LOG.info(" 按钮: %s", links[:20])
- _LOG.info(" 文本: %s", [t.strip()[:30] for t in texts[:10]])
- return 0
- finally:
- stop[0] = True
- conn.close()
- if __name__ == "__main__":
- sys.exit(main())
|