What a clone lacked: the gates went green with a thousand skipped tests and said nothing, every login script assumed a worktree-pool slot and its probe account, the client defaulted to the maintainer's account, a docker path and a home directory were in the code, the temp files broke on GNU coreutils, and two generators could only run against a sibling repo. Now the test gates print how many data-gated tests skipped and why; a scripted run logs in as the account its checkout declares in `.probe-identity` or as the three variables name, never a default, and the client refuses a scripted login on any other account; the event and message tables regenerate from vendored inputs, byte for byte; the docs state the real prerequisites. Out of the tree, into the maintainer's own tooling: the worktree pool, its hooks, the perf leg runner, the cross-platform compile and the Vulkan container leg — a way of working, and setups not every machine has. One hook stays: no writes into the install. Two tests that could never run are gone with their subject: the quest-timer geometry diff compared a copy of the window that no longer exists (and joined a chain path onto a folder, so it always skipped), and the FrameXML flag gate now reads the stock files off the player's own patch chain instead of an extracted folder only one machine had. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
82 lines
3.3 KiB
Rust
82 lines
3.3 KiB
Rust
//! Diagnostic probe: stream object creates and print each unit's decoded
|
|
//! `UNIT_FIELD_FACTIONTEMPLATE` (+ level/display id as sanity anchors), to check the descriptor
|
|
//! decode against the server DB's `creature_template.faction`.
|
|
//!
|
|
//! Run: `cargo run -p benilla-protocol --example faction_probe -- probeN pprobeN [host]`
|
|
//! — a probe account (the `probe` skill). The account is a REQUIRED arg with no default: a
|
|
//! default is somebody's account, and a probe login there kicks their live session (decision
|
|
//! 0530).
|
|
|
|
use std::time::{Duration, Instant};
|
|
|
|
use anyhow::{Context, Result};
|
|
use benilla_protocol::{decode, EntityKind, SessionEvent, WorldSession, WORLD_PORT};
|
|
|
|
fn main() -> Result<()> {
|
|
let mut args = std::env::args().skip(1);
|
|
let user = args
|
|
.next()
|
|
.context("usage: faction_probe -- <probeN> <pprobeN> [host] (a probe account)")?;
|
|
let pass = args
|
|
.next()
|
|
.context("usage: faction_probe -- <probeN> <pprobeN> [host] (a probe account)")?;
|
|
let host = args.next().unwrap_or_else(|| "localhost".into());
|
|
|
|
let logon = benilla_protocol::logon(&host, &user, &pass)?;
|
|
let world_addr = logon
|
|
.realms
|
|
.first()
|
|
.map(|r| r.address.clone())
|
|
.unwrap_or_else(|| format!("{host}:{WORLD_PORT}"));
|
|
let mut session = WorldSession::connect(&world_addr, &user, logon.session_key)?;
|
|
let characters = session.char_enum()?;
|
|
let character = characters.first().context("no characters")?;
|
|
let self_guid = character.guid;
|
|
println!("logging in '{}' (guid {self_guid})", character.name);
|
|
session.player_login(self_guid)?;
|
|
session.set_active_mover(self_guid)?;
|
|
session.set_read_timeout(Some(Duration::from_secs(2)))?;
|
|
|
|
let deadline = Instant::now() + Duration::from_secs(8);
|
|
while Instant::now() < deadline {
|
|
let Ok(msg) = session.recv() else { continue };
|
|
for ev in decode(msg) {
|
|
match ev {
|
|
SessionEvent::ObjectCreate {
|
|
guid,
|
|
kind,
|
|
display_id,
|
|
fields,
|
|
..
|
|
} if matches!(kind, EntityKind::Unit | EntityKind::Player) => {
|
|
let me = if guid == self_guid { " (self)" } else { "" };
|
|
println!(
|
|
"{kind:?} guid={guid}{me} display={display_id:?} level={:?} faction_tpl={:?}",
|
|
fields.unit_level(),
|
|
fields.unit_faction_template(),
|
|
);
|
|
}
|
|
SessionEvent::ObjectValues { guid, fields } => {
|
|
if let Some(f) = fields.unit_faction_template() {
|
|
println!("Values guid={guid} faction_tpl={f}");
|
|
}
|
|
}
|
|
SessionEvent::Reputations { standings } => {
|
|
let set: Vec<(usize, u8, i32)> = standings
|
|
.iter()
|
|
.enumerate()
|
|
.filter(|(_, &(f, s))| f != 0 || s != 0)
|
|
.map(|(i, &(f, s))| (i, f, s))
|
|
.collect();
|
|
println!(
|
|
"Reputations: {} slots, non-zero (idx, flags, standing): {set:?}",
|
|
standings.len()
|
|
);
|
|
}
|
|
_ => {}
|
|
}
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|