Files
Sam SungandClaude Opus 5.5 4dc33b4afd Comments in benilla-protocol: the second read, citations on the pinned revision and restored facts (#375)
The second read of `benilla-protocol`'s comments, the last step #41 asked for: that crate's comments were rewritten to the rule before second readers existed. Four readers compared every file's comments against their state before the rewrite and against the code as it is now.

Fixes #41.

- **Citations.** vmangos line citations are re-pointed to the pinned revision: off-by-a-few lines (`Pet.cpp`, `Guild.cpp`, `Petition.cpp`, `LootHandler.cpp`, `ChatHandler.cpp`), and paths the rewrite dropped where a bare file name is ambiguous (`Server/Packets/Spell.cpp` against `Spells/Spell.cpp`, the two `Item.cpp`, `Group.cpp` and `Chat.cpp`). The gossip-hello citation is `NPCHandler.cpp:347`.
- **Facts restored.** The move-time-skipped chain (`0x603b40` → `0x601560` → `0x61ab90`), the addon-message TAB surviving vmangos's chat sanitizer, the zone-under-attack sender, `SMSG_ADDON_INFO` answering the auth session's addon block, the officer-note permission gate, and `SMSG_ITEM_COOLDOWN` on equipping an item with an on-use spell (the old text said a proc).
- **Deviation labels.** A label now carries its reason, or goes when the behaviour is only unbuilt (the survey window, the group XP bonus, the NPC-text language garble).
- **Two examples.** `park_probe` and `login_refusal_probe` took a hard-coded local account; they now read `WOW_USER` and `WOW_PASS`.
- **Verification.** Every file strips to identical code apart from the two examples; `cargo fmt --check` is clean.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 01:29:00 +07:00

65 lines
2.4 KiB
Rust

//! Live probe: the character-select park behaviours the glue screens rely on. A logout ends in
//! `SMSG_LOGOUT_COMPLETE` and a reconnect re-serves the roster; a socket parked at character
//! select for 130 s still logs in, since vmangos does not kick a quiet authenticated socket.
//!
//! Needs the local vmangos and an account in `WOW_USER`/`WOW_PASS`.
use std::time::Duration;
use benilla_protocol::{logon, WorldSession, WORLD_PORT};
fn connect(user: &str, pass: &str) -> anyhow::Result<WorldSession> {
let l = logon("localhost", user, pass)?;
let addr = l
.realms
.first()
.map(|r| r.address.clone())
.unwrap_or_else(|| format!("localhost:{WORLD_PORT}"));
WorldSession::connect(&addr, user, l.session_key)
}
fn main() -> anyhow::Result<()> {
let user = std::env::var("WOW_USER").map_err(|_| anyhow::anyhow!("set WOW_USER"))?;
let pass = std::env::var("WOW_PASS").map_err(|_| anyhow::anyhow!("set WOW_PASS"))?;
let (user, pass) = (user.as_str(), pass.as_str());
// ── 1 · logout round-trip ──
let mut s = connect(user, pass)?;
let chars = s.char_enum()?;
println!(
"roster: {:?}",
chars.iter().map(|c| &c.name).collect::<Vec<_>>()
);
let c = &chars[0];
s.player_login(c.guid)?;
s.set_active_mover(c.guid)?;
println!("logged in as {} — requesting logout in 2s", c.name);
std::thread::sleep(Duration::from_secs(2));
s.set_read_timeout(Some(Duration::from_secs(1)))?;
s.logout(Duration::from_secs(25))?;
println!("PASS: SMSG_LOGOUT_COMPLETE received");
drop(s);
// A fresh connection re-serves the roster, as the app's relist does.
let mut s = connect(user, pass)?;
let n = s.char_enum()?.len();
println!("PASS: post-logout reconnect roster has {n} chars");
drop(s);
// ── 2 · idle park ──
let mut s = connect(user, pass)?;
let chars = s.char_enum()?;
println!("parking at character select for 130s…");
std::thread::sleep(Duration::from_secs(130));
match s.player_login(chars[0].guid).and_then(|()| {
s.set_active_mover(chars[0].guid)?;
// Any post-login packet shows the world streams.
s.set_read_timeout(Some(Duration::from_secs(5)))?;
s.recv().map(|p| p.name())
}) {
Ok(pkt) => println!("PASS: idle-parked login works (first packet: {pkt})"),
Err(e) => println!("KICKED: idle park failed login: {e:#} (self-heals via relist)"),
}
Ok(())
}