| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- """分层可导入、核心契约、消息号无碰撞 — 骨架期测试的真实现版。"""
- import pbot
- from pbot.codec.frame import Frame, build_frame, parse_frame
- from pbot.game.messages import CsMsg, ScMsg
- from pbot.types import PointCode, pack_point, unpack_point
- from pbot.world.mirror import WorldMirror
- from pbot.world.update import (
- WorldUpdater,
- body_json,
- decode_body_variants,
- y_with_flag,
- )
- def sc(mid: int, recog: int, p1: int, p2: int, p3: int, body: bytes = b"") -> "Frame":
- """构造服务器帧(测试辅助): build → parse 得 Frame。"""
- return parse_frame(build_frame(mid, recog, p1, p2, p3, body))
- def test_top_level_exports_are_importable() -> None:
- """Given: 包顶层声明公共契约 When: 逐个访问 Then: 全部存在。"""
- for name in pbot.__all__:
- assert getattr(pbot, name) is not None
- def test_pack_point_roundtrip() -> None:
- """Given: 平面坐标 When: pack 后 unpack Then: 还原原值 (Y<<16|X 布局)。"""
- code: PointCode = pack_point(289, 615)
- assert code == (615 << 16) | 289
- assert unpack_point(code) == (289, 615)
- def test_sc_and_cs_msg_ids_are_unique_within_each_table() -> None:
- """Given: 两个消息号表 When: 取值集合 Then: 各自内部无重复值。"""
- sc_values = [m.value for m in ScMsg]
- cs_values = [m.value for m in CsMsg]
- assert len(sc_values) == len(set(sc_values))
- assert len(cs_values) == len(set(cs_values))
- def test_all_game_layers_importable() -> None:
- """Given: 分层架构 When: 自底向上导入每层 Then: 无循环依赖错误。"""
- from pbot import bot, codec, game, login, transport, world
- assert bot is not None and codec is not None
- assert game is not None and login is not None
- assert transport is not None and world is not None
- def test_cs_walk_layout_matches_capture() -> None:
- """Given: 实测帧布局 When: 检查关键消息号 Then: 与 backup 实测值一致。"""
- assert CsMsg.WALK == 3011
- assert CsMsg.RUN == 3013
- assert CsMsg.ATTACK == 3014
- assert CsMsg.HEARTBEAT == 60000
- assert ScMsg.BATCH == -1
- def test_y_flag_bit_masked() -> None:
- """Given: Y 带 bit11 标志(2048) When: _y_with_flag Then: 掩掉标志位。
- 实测(quest_bot3 SC51 解析): bit11 是编码标志非坐标 — 旧实现把它当坐标
- 导致出生坐标整体读错(如 (23,25) 读成 (25,0))。
- """
- assert y_with_flag(2048 + 25) == 25
- assert y_with_flag(25) == 25
- def test_body_json_decode6_variant() -> None:
- """Given: encode6(JSON) body(SC11 同款) When: body_json Then: 解出 dict。"""
- from pbot.codec.bitbuf import encode6
- raw = b'{"UserID":"123","X":10,"Y":20}'
- f = sc(11, 10, 20, 0, 0, body=encode6(raw))
- j = body_json(f)
- assert j["UserID"] == "123" and j["X"] == 10
- def test_body_variants_zlib_wrapped() -> None:
- """Given: zlib(encode6(JSON)) body When: decode_body_variants Then: 含明文 JSON。"""
- import zlib
- from pbot.codec.bitbuf import encode6
- inner = encode6(b'{"MapName":"xx"}')
- blob = zlib.compress(inner)
- variants = decode_body_variants(blob)
- assert b'{"MapName":"xx"}' in variants
- def test_sc51_sets_walk_position() -> None:
- """Given: SC51(recog=22, p1=26, body=MapName) When: apply Then:
- 位置=SC51 坐标(cap_live2 定案: 真客户端首步起点=(22,26) 与 SC51 一致,
- SC50.p2 是回家位墙格不采信)。"""
- f = sc(51, 22, 26, 2048, 0, body=b'{"MapName":"xx","MapId":"0"}')
- world = WorldMirror()
- world.me.x, world.me.y = 0, 1 # SC50 的回家位(墙格)
- WorldUpdater().apply(world, f)
- assert world.me.map_name == "xx"
- assert world.me.map_id == "0"
- assert (world.me.x, world.me.y) == (22, 26) # SC51 覆盖为真实位置
- assert any(e.kind == "map" for e in world.events)
- def test_sc28_pull_back_updates_authority() -> None:
- """Given: 主玩家在(20,26), SC28(recog=21,p1=27,p2=dir) When: apply Then:
- 权威位更新为 (21,27)(SC28 布局 recog=X, p1=Y, p2=dir — 盟重探针定案)。"""
- world = WorldMirror()
- world.me.x, world.me.y = 20, 26
- f = sc(28, 21, 27, 4, 0)
- WorldUpdater().apply(world, f)
- assert (world.me.x, world.me.y) == (21, 27)
- assert world.me.dir == 4
- def test_sc28_zero_frame_ignored() -> None:
- """Given: SC28 (0,0) 清位帧 When: apply Then: 忽略, 坐标不变。"""
- world = WorldMirror()
- world.me.x, world.me.y = 20, 26
- f = sc(28, 0, 0, 0, 0)
- WorldUpdater().apply(world, f)
- assert (world.me.x, world.me.y) == (20, 26)
- def test_sc11_self_echo_confirms_move() -> None:
- """Given: 主玩家 uid=u1 在(20,26), SC11 body.UserID=u1 recog=21,p1=2048+27
- When: apply Then: 权威坐标更新 (21,27) — 自回显即服务器确认移动。"""
- from pbot.codec.bitbuf import encode6
- world = WorldMirror()
- world.me.uid = "u1"
- world.me.x, world.me.y = 20, 26
- body = encode6(b'{"UserID":"u1"}')
- f = sc(11, 21, 2048 + 27, 0, 0, body=body)
- WorldUpdater().apply(world, f)
- assert (world.me.x, world.me.y) == (21, 27)
- assert any(e.kind == "self_move_confirmed" for e in world.events)
- def test_sc53_hp_pipe_format() -> None:
- """Given: SC53 body=encode6("u1&95&100&30&50|1") When: apply Then: HP=95/100。"""
- from pbot.codec.bitbuf import encode6
- world = WorldMirror()
- world.me.uid = "u1"
- f = sc(53, 0, 0, 0, 0, body=encode6(b"u1&95&100&30&50|1"))
- WorldUpdater().apply(world, f)
- assert (world.me.hp, world.me.max_hp) == (95, 100)
|