diff --git a/crates/benilla-protocol/examples/cooldown_probe.rs b/crates/benilla-protocol/examples/cooldown_probe.rs index 39361af4..083afb95 100644 --- a/crates/benilla-protocol/examples/cooldown_probe.rs +++ b/crates/benilla-protocol/examples/cooldown_probe.rs @@ -1,13 +1,13 @@ //! Diagnostic probe: the server's cooldown window for Charge (spell 100: `recoveryTime 0`, //! category 44, `categoryRecoveryTime 15000`) against the client's 15 s sweep. It charges a //! Northshire Kobold Vermin (entry 6), then recasts every 200 ms. vmangos checks the cooldown -//! first in `CheckCast` (`Spell.cpp:5369`), so the first result other than +//! near the top of `CheckCast` (`Spell.cpp:5369`), so the first result other than //! `SPELL_FAILED_NOT_READY` (60), or a second `SMSG_SPELL_GO`, marks the server's cooldown end //! relative to the first GO. //! //! Run: `cargo run -p benilla-protocol --example cooldown_probe -- probeN [host]` on a //! probe account with a warrior (a login kicks whoever is on the account); `.learn` needs -//! gmlevel 5 (`SEC_DEVELOPER`). +//! gmlevel 5 (`SEC_DEVELOPER`). It is a combat probe, so it never runs unattended. use std::time::{Duration, Instant}; diff --git a/crates/benilla-protocol/examples/login_refusal_probe.rs b/crates/benilla-protocol/examples/login_refusal_probe.rs index 9ca7a0af..2bb2f039 100644 --- a/crates/benilla-protocol/examples/login_refusal_probe.rs +++ b/crates/benilla-protocol/examples/login_refusal_probe.rs @@ -5,7 +5,7 @@ //! and that a valid pick then works on the same socket. //! //! A creature guid trips the stateless `!packet.guid.IsPlayer()` guard. Needs the local vmangos -//! and account `two`/`ptwo`. +//! and an account in `WOW_USER`/`WOW_PASS`. use std::time::Duration; @@ -25,7 +25,9 @@ fn connect(user: &str, pass: &str) -> anyhow::Result { } fn main() -> anyhow::Result<()> { - let (user, pass) = ("two", "ptwo"); + 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()); let mut s = connect(user, pass)?; let chars = s.char_enum()?; println!( diff --git a/crates/benilla-protocol/examples/park_probe.rs b/crates/benilla-protocol/examples/park_probe.rs index 3badbb46..f29be9ee 100644 --- a/crates/benilla-protocol/examples/park_probe.rs +++ b/crates/benilla-protocol/examples/park_probe.rs @@ -2,7 +2,7 @@ //! `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 account `two`/`ptwo`. +//! Needs the local vmangos and an account in `WOW_USER`/`WOW_PASS`. use std::time::Duration; @@ -19,7 +19,9 @@ fn connect(user: &str, pass: &str) -> anyhow::Result { } fn main() -> anyhow::Result<()> { - let (user, pass) = ("two", "ptwo"); + 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)?; diff --git a/crates/benilla-protocol/examples/srp_encoding_probe.rs b/crates/benilla-protocol/examples/srp_encoding_probe.rs index 43006735..2a47dad1 100644 --- a/crates/benilla-protocol/examples/srp_encoding_probe.rs +++ b/crates/benilla-protocol/examples/srp_encoding_probe.rs @@ -9,8 +9,8 @@ //! ``` //! //! `--stress N` runs N ordinary fixed-width handshakes and reports the failure rate, waiting out -//! realmd's lockout: 60 s after `WrongPass.MaxAttempts` (default 10) failures, during which it -//! answers `0x08 WOW_FAIL_DB_BUSY`. +//! realmd's lockout: `WrongPass.MaxAttempts` (default 10) failures within 60 s lock the IP out +//! for 60 s, answered with `0x08 WOW_FAIL_DB_BUSY`. use std::net::TcpStream; use std::time::Duration; diff --git a/crates/benilla-protocol/src/auth.rs b/crates/benilla-protocol/src/auth.rs index 29d5c108..552ad544 100644 --- a/crates/benilla-protocol/src/auth.rs +++ b/crates/benilla-protocol/src/auth.rs @@ -165,7 +165,8 @@ const INTEGRITY_HASH_5875_MACOS: [u8; 20] = [ ]; /// The integrity digest `H` for `crc_salt`, known only for [`MANGOS_VERSION_CHALLENGE`]. -/// Deviation: a stored constant, not a hash of the install, which may lack the five binaries. +/// Deviation: a stored per-OS constant, not the reference's HMAC over its own executables +/// (`0x5b1170`), because every mangos-family realmd issues this one salt. fn integrity_hash(crc_salt: &[u8; 16]) -> Option<[u8; 20]> { if *crc_salt != MANGOS_VERSION_CHALLENGE { return None; diff --git a/crates/benilla-protocol/src/bin/benilla-world/probes/mod.rs b/crates/benilla-protocol/src/bin/benilla-world/probes/mod.rs index a3200306..59151c89 100644 --- a/crates/benilla-protocol/src/bin/benilla-world/probes/mod.rs +++ b/crates/benilla-protocol/src/bin/benilla-world/probes/mod.rs @@ -38,7 +38,7 @@ pub(crate) trait Probe { // Quest constants shared by several probes. /// Onto Marshal McBride, the `--quest` turn-in NPC and quest 7's giver and ender. -pub(crate) const QUEST_TURNIN_TP: &str = ".go xyz -8902.59 -162.606 82.0223"; // onto Marshal McBride +pub(crate) const QUEST_TURNIN_TP: &str = ".go xyz -8902.59 -162.606 82.0223"; pub(crate) const QUEST_TURNIN_ENTRY: u32 = 197; // Marshal McBride, who takes 783 /// `PLAYER_QUEST_LOG_1_1`: `UNIT_END` (188) + 0xA, 3 fields per slot for 20 slots /// (`UpdateFields_1_12_1.h:128`). diff --git a/crates/benilla-protocol/src/events.rs b/crates/benilla-protocol/src/events.rs index 30a058ca..6a1a0d2f 100644 --- a/crates/benilla-protocol/src/events.rs +++ b/crates/benilla-protocol/src/events.rs @@ -229,7 +229,8 @@ pub enum SessionEvent { /// cinematic camera (`Player::UpdateCinematic`), despawning the world around the body. CinematicTriggered { cinematic_id: u32 }, /// `MSG_MOVE_TIME_SKIPPED`: not a pose. The mover's relay stamp advances by `lag_ms`, as the - /// reference's `[CMovement+0xac] += lag` (`0x603b40`), or its next packet is scheduled late. + /// reference's `[CMovement+0xac] += lag` (`0x603b40` → `0x601560` → `0x61ab90`), or its next + /// packet is scheduled late. MoveTimeSkipped { guid: u64, lag_ms: u32 }, /// A server path: `path` is the travel-order polyline from `start`, walked at constant speed /// over `duration_ms`; a stop, a zero duration or fewer than two points leaves it empty. diff --git a/crates/benilla-protocol/src/messages/bank.rs b/crates/benilla-protocol/src/messages/bank.rs index e88a1a80..ada779c0 100644 --- a/crates/benilla-protocol/src/messages/bank.rs +++ b/crates/benilla-protocol/src/messages/bank.rs @@ -5,7 +5,7 @@ use std::io; use crate::wire::{read_u32_le, read_u64_le}; -/// `SMSG_BUY_BANK_SLOT_RESULT`'s reason (`BANK_SLOT_*`, vmangos `Player.h:91-94`). +/// `SMSG_BUY_BANK_SLOT_RESULT`'s reason (`ERR_BANKSLOT_*`, vmangos `Player.h:91-94`). pub mod bank_slot_result { pub const FAILED_TOO_MANY: u32 = 0; pub const INSUFFICIENT_FUNDS: u32 = 1; diff --git a/crates/benilla-protocol/src/messages/battlefield.rs b/crates/benilla-protocol/src/messages/battlefield.rs index d4270c03..b4bc954a 100644 --- a/crates/benilla-protocol/src/messages/battlefield.rs +++ b/crates/benilla-protocol/src/messages/battlefield.rs @@ -95,7 +95,8 @@ pub struct PvpLogData { pub rows: Vec, } -/// Deviation: every row is kept; the reference has 80 row blocks and does not clamp the count. +/// Deviation: every row is kept, because the reference takes the count unclamped into its 80 +/// row blocks and a larger one overruns them. pub(super) fn read_pvp_log_data(r: &mut impl Read) -> io::Result { let ended = read_u8(r)? != 0; let winner = if ended { Some(read_u8(r)?) } else { None }; diff --git a/crates/benilla-protocol/src/messages/broadcast.rs b/crates/benilla-protocol/src/messages/broadcast.rs index 05813d6c..d50926a5 100644 --- a/crates/benilla-protocol/src/messages/broadcast.rs +++ b/crates/benilla-protocol/src/messages/broadcast.rs @@ -17,7 +17,8 @@ pub(super) fn read_server_message(r: &mut &[u8]) -> io::Result<(u32, String)> { /// `SMSG_ZONE_UNDER_ATTACK` (`Server/Packets/Misc.cpp:451-454`, handler `0x49dcc0`): the attacked /// area's `AreaTable.dbc` id, whose own name fills the text. vmangos sends it map-wide to the -/// enemy team when a player kills a guard or PvP-enabling creature, once per area per 10 s. +/// enemy team when a player kills a guard or PvP-enabling creature, once per area per 10 s +/// (`Creature.cpp:2889`). pub(super) fn read_zone_under_attack(r: &mut &[u8]) -> io::Result { read_u32_le(r) } @@ -25,7 +26,7 @@ pub(super) fn read_zone_under_attack(r: &mut &[u8]) -> io::Result { /// `SMSG_DEFENSE_MESSAGE` (`Maps/Map.cpp:1868-1884`, handler `0x49de30`): `u32` zone id, `u32` /// length counting the NUL, then the text. The reference skips exactly `length` bytes /// (`0x419ac0`) and drops the line when that overruns the packet, so an overrun errors here. -/// Deviation: text without a NUL stops at `length`, where the reference reads out of bounds. +/// Deviation: text without a NUL stops at `length`, because the reference reads on out of bounds. pub(super) fn read_defense_message(r: &mut &[u8]) -> io::Result<(u32, String)> { let zone_id = read_u32_le(r)?; let length = read_u32_le(r)? as usize; diff --git a/crates/benilla-protocol/src/messages/chat.rs b/crates/benilla-protocol/src/messages/chat.rs index 023fb784..f5c56342 100644 --- a/crates/benilla-protocol/src/messages/chat.rs +++ b/crates/benilla-protocol/src/messages/chat.rs @@ -33,8 +33,9 @@ pub const CHAT_MSG_RAID_LEADER: u8 = 0x57; pub const CHAT_MSG_RAID_WARNING: u8 = 0x58; pub const CHAT_MSG_RAID_BOSS_WHISPER: u8 = 0x59; pub const CHAT_MSG_RAID_BOSS_EMOTE: u8 = 0x5A; -/// The server's "your message was filtered" notice, which the chat frame formats as -/// `CHAT_FILTERED`; the client's spam and profanity filters exempt it (`0x49aacc`). +/// The server's "your message was filtered" notice: its text is the addressee's name, which the +/// chat frame formats into `CHAT_FILTERED`; the client's spam and profanity filters exempt it +/// (`0x49aacc`). pub const CHAT_MSG_FILTERED: u8 = 0x5B; pub const CHAT_MSG_BATTLEGROUND: u8 = 0x5C; pub const CHAT_MSG_BATTLEGROUND_LEADER: u8 = 0x5D; diff --git a/crates/benilla-protocol/src/messages/death.rs b/crates/benilla-protocol/src/messages/death.rs index 169edfe4..1a8df397 100644 --- a/crates/benilla-protocol/src/messages/death.rs +++ b/crates/benilla-protocol/src/messages/death.rs @@ -5,7 +5,7 @@ use std::io; use crate::wire::{read_cstring, read_f32_le, read_i32_le, read_u32_le, read_u64_le, read_u8}; /// `MSG_CORPSE_QUERY`'s answer (`QueryHandler.cpp:258-304`), a lone `u8(0)` when not found; the -/// request is the same opcode, empty. The server also sends an unprompted not-found when the +/// request is the same opcode, empty. The server also sends an unprompted not-found when a looted /// corpse turns to bones (`Map.cpp:3624-3629`), which means "drop the marker". #[derive(Debug, Clone, PartialEq)] pub struct CorpseLocation { @@ -48,7 +48,7 @@ pub(super) fn read_corpse_reclaim_delay(r: &mut &[u8]) -> io::Result { /// `SMSG_RESURRECT_REQUEST`, a resurrection offer (`Spell.cpp:5024-5044`). `sickness` warns the /// accept brings resurrection sickness, `has_timer` keeps the reclaim-delay gate, and the stock -/// popup picks its variant by the two. +/// popup picks its variant by the two. `name` is empty for a player caster, named by guid instead. #[derive(Debug, Clone, PartialEq)] pub struct ResurrectRequestBody { pub caster: u64, diff --git a/crates/benilla-protocol/src/messages/gossip.rs b/crates/benilla-protocol/src/messages/gossip.rs index 5d5e93ab..b7b78a59 100644 --- a/crates/benilla-protocol/src/messages/gossip.rs +++ b/crates/benilla-protocol/src/messages/gossip.rs @@ -24,7 +24,7 @@ pub struct QuestOption { } /// `CMSG_GOSSIP_HELLO` body: the NPC's full guid (`Npc.cpp:3`); it works on any interactable -/// creature, gossip flag or not (`Player.cpp:347`). +/// creature, gossip flag or not (`NPCHandler.cpp:347`). pub fn gossip_hello(npc_guid: u64) -> Vec { npc_guid.to_le_bytes().to_vec() } @@ -108,8 +108,8 @@ pub const NPC_TEXT_BLOCKS: usize = 8; /// Read `SMSG_NPC_TEXT_UPDATE` (vmangos `GossipDef.cpp:298-369`), all eight blocks undecided; the /// greeting is picked when the frame opens, by [`select_greeting`]. /// -/// Deviation: the 1.12 client garbles a block in a non-zero language (`0x49b560`); we drop the -/// language because no 1.12 record sets one. +/// The language is parsed and dropped: the 1.12 client garbles a block in a non-zero language +/// (`0x49b560`), which is not built, and no 1.12 record is known to set one. pub(super) fn read_npc_text_update(r: &mut &[u8]) -> io::Result<(u32, Vec)> { let text_id = read_u32_le(r)?; let mut blocks = Vec::with_capacity(NPC_TEXT_BLOCKS); diff --git a/crates/benilla-protocol/src/messages/group.rs b/crates/benilla-protocol/src/messages/group.rs index e8e5c6af..e0ef1756 100644 --- a/crates/benilla-protocol/src/messages/group.rs +++ b/crates/benilla-protocol/src/messages/group.rs @@ -11,7 +11,7 @@ use crate::wire::{ }; /// The raid-assistant bit of a member's flags byte; bits 0-2 are the subgroup -/// (`Group.cpp:158,166`). +/// (`Group/Group.cpp:1382,1394`). pub const GROUP_MEMBER_ASSISTANT: u8 = 0x80; /// vmangos `GroupMemberStatus` (`Group/Group.h:102-111`); bit `0x20` is never set. @@ -51,7 +51,7 @@ pub mod party_result { pub struct GroupMemberEntry { pub name: String, pub guid: u64, - /// [`member_status`] bits (`GetGroupMemberStatus`, `Group.cpp:45-63`). + /// [`member_status`] bits (`GetGroupMemberStatus`, `Group/Group.cpp:45-63`). pub status: u8, /// Subgroup in bits 0-2, plus [`GROUP_MEMBER_ASSISTANT`]. pub flags: u8, diff --git a/crates/benilla-protocol/src/messages/guild.rs b/crates/benilla-protocol/src/messages/guild.rs index 0bbc5183..b432ce2f 100644 --- a/crates/benilla-protocol/src/messages/guild.rs +++ b/crates/benilla-protocol/src/messages/guild.rs @@ -3,8 +3,9 @@ //! //! Deviation: string reads are unbounded. The reference `0x4191b0` caps each field, counting the //! NUL (roster name `0x30`, notes `0x80`, MOTD `0x200`, info `0x7d0`, guild name `0x60`, rank name -//! `0x40`), and on overflow empties it and no-ops every later read in the packet; every cap is far -//! above the server's own length limits, so a legitimate packet reads the same. +//! `0x40`), and on overflow empties it and no-ops every later read in the packet. Unbounded reads +//! cannot poison a packet, and every cap is far above the server's own length limits, so a +//! legitimate packet reads the same. use std::io::{self, Read}; @@ -550,7 +551,8 @@ pub fn guild_set_public_note(name: &str, note: &str) -> Vec { two_cstring_body(name, note) } -/// Body of `CMSG_GUILD_SET_OFFICER_NOTE` (`Server/Packets/Guild.cpp:67-71`): name, then note. +/// Body of `CMSG_GUILD_SET_OFFICER_NOTE` (`Server/Packets/Guild.cpp:67-71`): name, then note; +/// the server requires [`guild_rank_right::EDIT_OFFICER_NOTE`]. pub fn guild_set_officer_note(name: &str, note: &str) -> Vec { two_cstring_body(name, note) } diff --git a/crates/benilla-protocol/src/messages/instance.rs b/crates/benilla-protocol/src/messages/instance.rs index 640d36ff..840e1ede 100644 --- a/crates/benilla-protocol/src/messages/instance.rs +++ b/crates/benilla-protocol/src/messages/instance.rs @@ -68,7 +68,7 @@ pub enum InstanceResetFailure { impl InstanceResetFailure { /// Deviation: a reason of 3 or more is silent, where the reference prints an uninitialized - /// stack buffer; 3 is the server's `INSTANCERESET_FAIL_SILENTLY`. + /// stack buffer, because 3 is the server's `INSTANCERESET_FAIL_SILENTLY`. pub fn from_wire(reason: u32) -> Option { match reason { 0 => Some(Self::General), diff --git a/crates/benilla-protocol/src/messages/loot.rs b/crates/benilla-protocol/src/messages/loot.rs index feea98be..e01fec45 100644 --- a/crates/benilla-protocol/src/messages/loot.rs +++ b/crates/benilla-protocol/src/messages/loot.rs @@ -35,7 +35,7 @@ pub mod slot_type { /// `LootType` (vmangos `LootMgr.h:49-61`). Only these four reach the wire: `SendLoot` remaps /// skinning and insignia to `PICKPOCKETING`, fishing holes and fails to `FISHING` -/// (`Player.cpp:8117-8131`); `CMSG_LOOT` always gets `CORPSE` (`LootHandler.cpp:340-354`). +/// (`Player.cpp:8120-8136`); `CMSG_LOOT` always gets `CORPSE` (`LootHandler.cpp:380`). pub mod loot_type { pub const CORPSE: u8 = 1; pub const PICKPOCKETING: u8 = 2; diff --git a/crates/benilla-protocol/src/messages/mod.rs b/crates/benilla-protocol/src/messages/mod.rs index a22a00d1..5cffe85e 100644 --- a/crates/benilla-protocol/src/messages/mod.rs +++ b/crates/benilla-protocol/src/messages/mod.rs @@ -297,7 +297,7 @@ pub const LANGUAGE_ORCISH: u32 = 0x1; /// `LANG_ADDON` (vmangos `SharedDefines.h:270`): marks a chat line as addon data, not speech; /// 1.12 has no addon opcode, and the client routes such a line to `CHAT_MSG_ADDON`. The server /// skips language, flood and sanitize checks for it, never rewrites it, and allows it only on the -/// group, guild and channel lanes (`ChatHandler.cpp:49,84,176-218`). The 1.12 `SendAddonMessage` +/// group, guild and channel lanes (`ChatHandler.cpp:49,84,172-219`). The 1.12 `SendAddonMessage` /// (`0x49f920`) sends only PARTY, RAID, GUILD and BATTLEGROUND, and the receive side names any /// other lane "UNKNOWN" (`0x49aff4`). pub const LANGUAGE_ADDON: u32 = 0xFFFF_FFFF; diff --git a/crates/benilla-protocol/src/messages/movement.rs b/crates/benilla-protocol/src/messages/movement.rs index 869c4e67..32fd4eaa 100644 --- a/crates/benilla-protocol/src/messages/movement.rs +++ b/crates/benilla-protocol/src/messages/movement.rs @@ -100,7 +100,7 @@ impl SpeedKind { } /// A mode the server grants the controlling client, one `MOVEMENTFLAGS` bit each (vmangos -/// `MovementInfo.h:25-62`, reference setters `0x7c7280`-`0x7c7370`). Root stops translation and +/// `MovementInfo.h:28-62`, reference setters `0x7c7280`-`0x7c7370`). Root stops translation and /// falling but not turning (`0x618054`); water walk makes liquid walkable (aura 104); feather fall /// caps the fall at 7 yd/s instead of 60.148 (aura 105, `0x7c5d20`); hover lifts ground contact by /// 1.0 yd (aura 106, `0x6367b0`). Levitate (spell 1706) grants the last three at once. diff --git a/crates/benilla-protocol/src/messages/opcode.rs b/crates/benilla-protocol/src/messages/opcode.rs index 1271830b..70e42f78 100644 --- a/crates/benilla-protocol/src/messages/opcode.rs +++ b/crates/benilla-protocol/src/messages/opcode.rs @@ -60,9 +60,11 @@ pub const CMSG_SET_WATCHED_FACTION: u16 = 0x0318; // 792 pub const SMSG_AUTH_CHALLENGE: u16 = 0x01EC; pub const SMSG_AUTH_RESPONSE: u16 = 0x01EE; /// The Warden anticheat challenge; vmangos kicks a client that leaves it unanswered for 30 s -/// (`Warden::Update`). Deviation: no Warden ([`crate::WardenRequired`]), so the connect refuses. +/// (`Warden::Update`). Deviation: benilla has no Warden, so the connect refuses such a server +/// ([`crate::WardenRequired`]) because a session there would only be kicked. pub const SMSG_WARDEN_DATA: u16 = 0x02E6; -/// One record per `## Secure:` addon in `CMSG_AUTH_SESSION`, in order, with no count or names. +/// The answer to `CMSG_AUTH_SESSION`'s addon block: one record per `## Secure:` addon, in order, +/// with no count or names. pub const SMSG_ADDON_INFO: u16 = 0x02EF; pub const SMSG_COMPRESSED_UPDATE_OBJECT: u16 = 0x01F6; /// A zlib envelope of whole movement packets. Routine: vmangos switches a session to it after 300 @@ -222,7 +224,8 @@ pub const SMSG_CLEAR_COOLDOWN: u16 = 0x01DE; // 478 pub const SMSG_COOLDOWN_CHEAT: u16 = 0x01E1; // 481 /// A timed item's remaining life in seconds; the display reads this, not `ITEM_FIELD_DURATION` -/// (`Item.cpp:1094`). It shares the reference handler (`0x5e4f69`) with the enchant update below. +/// (`Item.cpp:1094`). Its reference handler is the enchant update's, forking on the opcode +/// (`0x5e4f69`). pub const SMSG_ITEM_TIME_UPDATE: u16 = 0x01EA; // 490 /// The only source of a temporary enchant's remaining time: the reference tooltip reads a @@ -607,8 +610,8 @@ pub const CMSG_GMTICKET_SYSTEMSTATUS: u16 = 0x021A; // 538 pub const SMSG_GMTICKET_SYSTEMSTATUS: u16 = 0x021B; // 539 /// A ticket-state push: `u32` 1 updated, 2 closed, 3 survey offered; vmangos never sends it. The -/// reference re-asks for the ticket on 1 (`0x5e7932`). Deviation: 3 opens no survey window, -/// since vmangos can never offer one. +/// reference re-asks for the ticket on 1 (`0x5e7932`); 2 and 3 are recorded, not acted on, and +/// the survey window 3 offers is not built. pub const SMSG_GM_TICKET_STATUS_UPDATE: u16 = 0x0328; // 808 // The bank: `CMSG_BANKER_ACTIVATE` opens a pure banker; `SMSG_SHOW_BANK` also arrives unasked @@ -891,9 +894,10 @@ pub const CMSG_GROUP_SWAP_SUB_GROUP: u16 = 0x0280; // 640 pub const CMSG_GROUP_RAID_CONVERT: u16 = 0x028E; // 654 pub const CMSG_GROUP_ASSISTANT_LEADER: u16 = 0x028F; // 655 pub const SMSG_PARTY_MEMBER_STATS_FULL: u16 = 0x02F2; // 754 -/// Both ways; the server's side is mode-prefixed (`Group.cpp:77-82` read, `:132-147` write). +/// Both ways; the server's side is mode-prefixed (`Packets/Group.cpp:77-82` read, `:132-147` +/// write). pub const MSG_RAID_TARGET_UPDATE: u16 = 0x0321; // 801 -/// Both ways: an empty body starts a check, a non-empty one answers (`Group.cpp:84-96`). +/// Both ways: an empty body starts a check, a non-empty one answers (`Packets/Group.cpp:84-96`). pub const MSG_RAID_READY_CHECK: u16 = 0x0322; // 802 /// Ask for our raid lockouts: empty body, sent by `RequestRaidInfo()` on every RaidFrame show. pub const CMSG_REQUEST_RAID_INFO: u16 = 0x02CD; // 717 @@ -975,7 +979,8 @@ pub const SMSG_UPDATE_WORLD_STATE: u16 = 0x02C3; // 707 // ── Instance and raid lockouts ── /// "You are now saved to this instance": a `u32` flag, 0 from vmangos (`0x4e7e60`; 1 adds a debug -/// prefix). Deviation: 2 or more prints nothing; the reference prints an uninitialized buffer. +/// prefix). Deviation: 2 or more prints nothing, because the reference prints an uninitialized +/// buffer. pub const SMSG_INSTANCE_SAVE_CREATED: u16 = 0x02CB; // 715 /// A raid-lockout warning: `u32 type`, `u32 mapId`, `u32 secondsUntilReset` (`0x49e1c0`). pub const SMSG_RAID_INSTANCE_MESSAGE: u16 = 0x02FA; // 762 diff --git a/crates/benilla-protocol/src/messages/packet.rs b/crates/benilla-protocol/src/messages/packet.rs index 81ba5be3..d0aae26e 100644 --- a/crates/benilla-protocol/src/messages/packet.rs +++ b/crates/benilla-protocol/src/messages/packet.rs @@ -409,7 +409,8 @@ pub enum ServerPacket { flags: u8, members: Vec<(u64, u8)>, }, - /// `SMSG_CHAT_PLAYER_NOT_FOUND`: the whisper target is not online (`Chat.cpp:26-29`). + /// `SMSG_CHAT_PLAYER_NOT_FOUND`: the whisper target is not online + /// (`Server/Packets/Chat.cpp:26-29`). ChatPlayerNotFound { name: String, }, @@ -420,7 +421,7 @@ pub enum ServerPacket { text: String, }, /// `SMSG_AREA_TRIGGER_MESSAGE`: why a trigger refused us, as `u32 length` then a cstring - /// (`WorldSession.cpp:882-898`). + /// (`WorldSession.cpp:883-898`). AreaTriggerMessage { text: String, }, @@ -751,7 +752,7 @@ pub enum ServerPacket { vendor: u64, items: Vec, }, - /// `SMSG_BUY_ITEM`: the vendor's stock after a purchase (`Item.cpp:190-196`). + /// `SMSG_BUY_ITEM`: the vendor's stock after a purchase (`Server/Packets/Item.cpp:190-196`). BuyItem { vendor: u64, slot: u32, diff --git a/crates/benilla-protocol/src/messages/parse.rs b/crates/benilla-protocol/src/messages/parse.rs index 8e589874..4419af05 100644 --- a/crates/benilla-protocol/src/messages/parse.rs +++ b/crates/benilla-protocol/src/messages/parse.rs @@ -230,7 +230,8 @@ fn parse_server_body( // bytes left, `u32 billingTimeRemaining, u8 billingPlanFlags, u32 billingTimeRested`; // then, for WAIT_QUEUE, `u32 position`. The 5 guarding a 9-byte group is the client's // and mis-parses a 6..=9 byte body; matched on purpose. Deviation: a body too short - // for the position gives `None`, because the client redisplays a stale position. + // for the position gives `None` where the client redisplays a stale global, because + // showing a stale queue position as current is a client bug. let result = read_u8(&mut r)?; let queued = result == super::AUTH_WAIT_QUEUE; let mut billing_time_rested = None; diff --git a/crates/benilla-protocol/src/messages/pet.rs b/crates/benilla-protocol/src/messages/pet.rs index 4e123b55..98e27b89 100644 --- a/crates/benilla-protocol/src/messages/pet.rs +++ b/crates/benilla-protocol/src/messages/pet.rs @@ -130,7 +130,7 @@ pub struct PetSpells { pub state: u32, /// The ten bar slots, in bar order. pub bar: [PetActionEntry; PET_ACTION_SLOTS], - /// The pet spellbook, packed like the bar; only a permanent pet has one (`Player.cpp:17549`). + /// The pet spellbook, packed like the bar; only a permanent pet has one (`Player.cpp:17547`). pub spells: Vec, pub cooldowns: Vec, } @@ -231,7 +231,7 @@ pub struct PetMode { pub state: u32, } -/// Read `SMSG_PET_MODE`: `u64 petGuid, u32 state` (`0x4bdb10`; vmangos `Packets/Pet.cpp:101-108`). +/// Read `SMSG_PET_MODE`: `u64 petGuid, u32 state` (`0x4bdb10`; vmangos `Packets/Pet.cpp:104-111`). pub(super) fn read_pet_mode(r: &mut impl Read) -> io::Result { Ok(PetMode { pet_guid: read_u64_le(r)?, @@ -239,7 +239,7 @@ pub(super) fn read_pet_mode(r: &mut impl Read) -> io::Result { }) } -/// Read `SMSG_PET_ACTION_FEEDBACK` (vmangos `Packets/Pet.cpp:87-90`): one reason byte. +/// Read `SMSG_PET_ACTION_FEEDBACK` (vmangos `Packets/Pet.cpp:90-93`): one reason byte. pub(super) fn read_pet_action_feedback(r: &mut impl Read) -> io::Result { read_u8(r) } diff --git a/crates/benilla-protocol/src/messages/petition.rs b/crates/benilla-protocol/src/messages/petition.rs index c46f24ef..2c47b3d0 100644 --- a/crates/benilla-protocol/src/messages/petition.rs +++ b/crates/benilla-protocol/src/messages/petition.rs @@ -13,7 +13,7 @@ use crate::wire::{ /// The guild charter's item entry, vmangos `GUILD_CHARTER` (`PetitionsHandler.cpp:37`). pub const CHARTER_ITEM_ENTRY: u32 = 5863; -/// The charter's display id, vmangos `CHARTER_DISPLAY_ID` (`PetitionsHandler.cpp:38`). +/// The charter's display id, vmangos `CHARTER_DISPLAY_ID` (`PetitionsHandler.cpp:39`). pub const CHARTER_DISPLAY_ID: u32 = 16161; /// The template-flag bit of a signable petition (vmangos `ItemPrototype.h:77`); the reference @@ -29,7 +29,7 @@ pub const MAX_PETITION_SIGNATURES: usize = 9; pub const CHARTER_NAME_MAX_LENGTH: usize = 24; /// The result code shared by `SMSG_PETITION_SIGN_RESULTS` and `SMSG_TURN_IN_PETITION_RESULTS` -/// (vmangos `PetitionSigns`, `Guild.h:147-154`); each packet uses its own subset. +/// (vmangos `PetitionSigns`, `Guild/Guild.h:147-154`); each packet uses its own subset. pub mod petition_result { /// Signed, or turned in; both packets. pub const OK: u32 = 0; @@ -52,13 +52,13 @@ pub mod petition_result { /// (`Petition.h:176`: "only 1 element is supported in the client"). #[derive(Debug, Clone, PartialEq, Eq, Default)] pub struct PetitionShowListEntry { - /// Row index, 1-based (`PetitionsHandler.cpp:501`). + /// Row index, 1-based (`PetitionsHandler.cpp:496`). pub index: u32, /// The item entry sold, [`CHARTER_ITEM_ENTRY`] in practice. pub charter_entry: u32, /// Its display id, [`CHARTER_DISPLAY_ID`] in practice. pub charter_display_id: u32, - /// Price in copper, an `int32` on the wire (vmangos charges 1000, `PetitionsHandler.cpp:39`). + /// Price in copper, an `int32` on the wire (vmangos charges 1000, `PetitionsHandler.cpp:38`). pub charter_cost: i32, /// vmangos sends 1; its header says a row "must be `&1` to show it in the UI" /// (`Petition.h:169`). @@ -79,7 +79,7 @@ pub struct PetitionShowList { pub(super) fn read_petition_show_list(r: &mut impl Read) -> io::Result { let npc = read_u64_le(r)?; let count = read_u8(r)?; - // vmangos sends exactly one charter (`PetitionsHandler.cpp:503`); 8 is generous. + // vmangos sends exactly one charter (`PetitionsHandler.cpp:504`); 8 is generous. let mut entries = Vec::with_capacity(capacity_hint(count, 8)); for _ in 0..count { entries.push(PetitionShowListEntry { @@ -170,9 +170,9 @@ pub struct PetitionQueryResponse { pub owner: u64, /// The proposed guild's name, carried by no other packet. pub name: String, - /// Free text on the charter; empty on vmangos (`PetitionsHandler.cpp:178`). + /// Free text on the charter; empty, as vmangos never sets it (`PetitionsHandler.cpp:177-183`). pub body_text: String, - /// vmangos sends 1 (`PetitionsHandler.cpp:179`); meaning unknown. + /// vmangos sends 1 (`PetitionsHandler.cpp:181`); meaning unknown. pub flags: u32, /// Signatures required, which the reference's Request-Signature button tests; vmangos sends 9 /// even when its `MinPetitionSigns` is lower (`PetitionsHandler.cpp:182`). @@ -189,7 +189,7 @@ pub struct PetitionQueryResponse { pub allowed_classes: u32, /// Race mask restriction, 0 on vmangos. pub allowed_races: u32, - /// Gender restriction: a `u16`, the packet's one odd width (`Packets/Petition.cpp:94`). + /// Gender restriction: a `u16`, the packet's one odd width (`Packets/Petition.cpp:95`). pub allowed_gender: u16, /// Minimum level, 0 on vmangos. pub allowed_min_level: u32, diff --git a/crates/benilla-protocol/src/messages/progression.rs b/crates/benilla-protocol/src/messages/progression.rs index 962afb77..8ba7843c 100644 --- a/crates/benilla-protocol/src/messages/progression.rs +++ b/crates/benilla-protocol/src/messages/progression.rs @@ -16,8 +16,8 @@ pub struct XpGain { } /// Read `SMSG_LOG_XPGAIN`: `u64 victim, u32 total, u8 type` (0 kill, 1 other), then for a kill -/// `u32 base, f32 groupBonus`. Deviation: the group bonus is read and dropped; vmangos always -/// sends 1.0, meaning none (`Player.cpp:3039`), so 1.12 shows no group-bonus line either. +/// `u32 base, f32 groupBonus`. The group bonus is read and dropped, its chat line not built; +/// vmangos always sends 1.0, meaning none (`Player.cpp:3039`). pub(super) fn read_xp_gain(r: &mut impl Read) -> io::Result { let victim = read_u64_le(r)?; let total = read_u32_le(r)?; diff --git a/crates/benilla-protocol/src/messages/quest/giver.rs b/crates/benilla-protocol/src/messages/quest/giver.rs index 56edfa86..473a8aaf 100644 --- a/crates/benilla-protocol/src/messages/quest/giver.rs +++ b/crates/benilla-protocol/src/messages/quest/giver.rs @@ -116,7 +116,7 @@ pub fn questgiver_status_query(npc: u64) -> Vec { } /// Body of `CMSG_QUESTGIVER_HELLO` (`Quest.cpp:16-19`): the NPC guid. The server answers it like -/// `CMSG_GOSSIP_HELLO`, through `SendPreparedGossip` (`QuestHandler.cpp:103`). +/// `CMSG_GOSSIP_HELLO`, through `SendPreparedGossip` (`QuestHandler.cpp:104`). pub fn questgiver_hello(npc: u64) -> Vec { npc.to_le_bytes().to_vec() } diff --git a/crates/benilla-protocol/src/messages/spellbook.rs b/crates/benilla-protocol/src/messages/spellbook.rs index dd946de7..81456ee7 100644 --- a/crates/benilla-protocol/src/messages/spellbook.rs +++ b/crates/benilla-protocol/src/messages/spellbook.rs @@ -41,28 +41,29 @@ pub(super) fn read_initial_spells(r: &mut impl Read) -> io::Result<(Vec, Ve Ok((spells, cooldowns)) } -/// Read `SMSG_LEARNED_SPELL` (vmangos `Spell.cpp:175-179`): `u16 spellId`, then an action-bar slot -/// the client does not use. The one message that adds to the book after login. +/// Read `SMSG_LEARNED_SPELL` (vmangos `Server/Packets/Spell.cpp:175-179`): `u16 spellId`, then +/// an action-bar slot the client does not use. The one message that adds to the book after login. pub(super) fn read_learned_spell(r: &mut impl Read) -> io::Result { let spell_id = read_u16_le(r)?; let _action_bar_slot = read_u16_le(r)?; Ok(spell_id) } -/// Read `SMSG_REMOVED_SPELL` (vmangos `Spell.cpp:181`): a bare `u16 spellId`, no action-bar slot. +/// Read `SMSG_REMOVED_SPELL` (vmangos `Server/Packets/Spell.cpp:181`): a bare `u16 spellId`, no +/// action-bar slot. pub(super) fn read_removed_spell(r: &mut impl Read) -> io::Result { read_u16_le(r) } -/// Read `SMSG_SUPERCEDED_SPELL` (vmangos `Spell.cpp:169-173`): `(oldSpellId, newSpellId)`; a -/// rank-up replaces the old spell in both the book and the action bar. +/// Read `SMSG_SUPERCEDED_SPELL` (vmangos `Server/Packets/Spell.cpp:169-173`): `(oldSpellId, +/// newSpellId)`; a rank-up replaces the old spell in both the book and the action bar. pub(super) fn read_superceded_spell(r: &mut impl Read) -> io::Result<(u16, u16)> { Ok((read_u16_le(r)?, read_u16_le(r)?)) } -/// Read `SMSG_SPELL_COOLDOWN` (vmangos `Spell.cpp:142-151`, client `0x6e9460`): a `u64` caster, -/// then `(spell, ms)` pairs to the end, with no flags byte in 1.12. `ms == 0` means the spell's own -/// `Spell.dbc` recovery times. Sent for school lockouts and pet cooldowns. +/// Read `SMSG_SPELL_COOLDOWN` (vmangos `Server/Packets/Spell.cpp:142-150`, client `0x6e9460`): a +/// `u64` caster, then `(spell, ms)` pairs to the end, with no flags byte in 1.12. `ms == 0` means +/// the spell's own `Spell.dbc` recovery times. Sent for school lockouts and pet cooldowns. pub(super) fn read_spell_cooldown(r: &mut &[u8]) -> io::Result<(u64, Vec<(u32, u32)>)> { let caster = read_u64_le(r)?; let mut cooldowns = Vec::new(); @@ -74,15 +75,18 @@ pub(super) fn read_spell_cooldown(r: &mut &[u8]) -> io::Result<(u64, Vec<(u32, u Ok((caster, cooldowns)) } -/// Read `SMSG_ITEM_COOLDOWN` (vmangos `Item.cpp:229-233`): `(item_guid, spell_id)`. The client -/// (`0x6e95d0`) gives the item a hardcoded 30 s cooldown; no duration is on the wire. +/// Read `SMSG_ITEM_COOLDOWN` (vmangos `Server/Packets/Item.cpp:229-233`): `(item_guid, spell_id)`, +/// sent when an item with an on-use spell is equipped (`Player::ApplyEquipCooldown`, +/// `Player.cpp:19358-19384`). The client (`0x6e95d0`) gives the item a hardcoded 30 s cooldown; no +/// duration is on the wire. pub(super) fn read_item_cooldown(r: &mut impl Read) -> io::Result<(u64, u32)> { Ok((read_u64_le(r)?, read_u32_le(r)?)) } -/// Read `SMSG_COOLDOWN_EVENT` or `SMSG_CLEAR_COOLDOWN` (vmangos `Spell.cpp:152-167`, client -/// `0x6e9670`): the `u32` spell id first, then the `u64` caster. EVENT starts the timers of an -/// on-hold (`SPELL_ATTR_COOLDOWN_ON_EVENT`) cooldown; CLEAR removes the cooldown. +/// Read `SMSG_COOLDOWN_EVENT` or `SMSG_CLEAR_COOLDOWN` (vmangos +/// `Server/Packets/Spell.cpp:152-167`, client `0x6e9670`): the `u32` spell id first, then the +/// `u64` caster. EVENT starts the timers of an on-hold (`SPELL_ATTR_COOLDOWN_ON_EVENT`) cooldown; +/// CLEAR removes the cooldown. pub(super) fn read_cooldown_event(r: &mut impl Read) -> io::Result<(u32, u64)> { Ok((read_u32_le(r)?, read_u64_le(r)?)) } diff --git a/crates/benilla-protocol/src/messages/spells.rs b/crates/benilla-protocol/src/messages/spells.rs index 1e70c096..9db976ab 100644 --- a/crates/benilla-protocol/src/messages/spells.rs +++ b/crates/benilla-protocol/src/messages/spells.rs @@ -268,8 +268,8 @@ pub(super) fn read_update_aura_duration(r: &mut impl Read) -> io::Result<(u8, u3 Ok((slot, remaining_ms)) } -/// Read `SMSG_PLAY_SPELL_VISUAL` (vmangos `Spell.cpp:54-58`): raw `u64` unit, `u32` kit id. The -/// client (`0x6e98d0`) checks the kit against `SpellVisualKit.dbc` and plays it at stage 0. +/// Read `SMSG_PLAY_SPELL_VISUAL` (vmangos `Packets/Spell.cpp:54-58`): raw `u64` unit, `u32` kit +/// id. The client (`0x6e98d0`) checks the kit against `SpellVisualKit.dbc` and plays it at stage 0. pub(super) fn read_play_spell_visual(r: &mut impl Read) -> io::Result<(u64, u32)> { let unit = read_u64_le(r)?; let kit_id = read_u32_le(r)?; diff --git a/crates/benilla-protocol/src/messages/update_object/fields/unit.rs b/crates/benilla-protocol/src/messages/update_object/fields/unit.rs index f52b8940..1ce69315 100644 --- a/crates/benilla-protocol/src/messages/update_object/fields/unit.rs +++ b/crates/benilla-protocol/src/messages/update_object/fields/unit.rs @@ -99,7 +99,8 @@ impl ObjectFields { self.unit_pet_number() != 0 } /// `UNIT_FIELD_PETNUMBER`: `GetUnitName` (`0x609210`) keys the pet-name cache on it when - /// nonzero; a `HIGHGUID_PET` guid's number is not a substitute, no name query answers it. + /// nonzero. A `HIGHGUID_PET` guid's number is no substitute: a companion's is never filed in + /// its charm info, so no pet-name query answers it. pub fn unit_pet_number(&self) -> u32 { self.get_u32(FIELD_UNIT_PETNUMBER).unwrap_or(0) } diff --git a/crates/benilla-protocol/src/world/writer/chat.rs b/crates/benilla-protocol/src/world/writer/chat.rs index f0cfcde6..d059e147 100644 --- a/crates/benilla-protocol/src/world/writer/chat.rs +++ b/crates/benilla-protocol/src/world/writer/chat.rs @@ -132,9 +132,10 @@ impl WorldWriter { ) } - /// Send an addon message (`SendAddonMessage`). Its language, [`messages::LANGUAGE_ADDON`], is - /// the only mark of addon data (`0x49f920`); vmangos gates it on `AddonChannel` and skips the - /// language gate, flood control and sanitizing. + /// Send an addon message (`SendAddonMessage`): `text` is the caller's composed `prefix` TAB + /// `message`, on the party, raid, guild or battleground lane. Its language, + /// [`messages::LANGUAGE_ADDON`], is the only mark of addon data (`0x49f920`); vmangos gates it + /// on `AddonChannel` and skips the language gate, flood control and sanitizing. pub fn send_addon_message(&mut self, chat_type: u32, text: &str) -> Result<()> { self.send( opcode::CMSG_MESSAGECHAT, diff --git a/crates/benilla-protocol/src/world/writer/gossip.rs b/crates/benilla-protocol/src/world/writer/gossip.rs index 4a9ca716..297a9512 100644 --- a/crates/benilla-protocol/src/world/writer/gossip.rs +++ b/crates/benilla-protocol/src/world/writer/gossip.rs @@ -1,5 +1,6 @@ //! The gossip sends. `CMSG_GOSSIP_HELLO` opens every NPC service window: vmangos accepts it for any -//! interactable creature (`CanInteractWithNPC` with `UNIT_NPC_FLAG_NONE`, `Player.cpp:347`). +//! interactable creature (`GetNPCIfCanInteractWith` with `UNIT_NPC_FLAG_NONE`, +//! `NPCHandler.cpp:347`). use anyhow::Result; diff --git a/crates/benilla-protocol/tests/client.rs b/crates/benilla-protocol/tests/client.rs index e49efe7f..749e6c30 100644 --- a/crates/benilla-protocol/tests/client.rs +++ b/crates/benilla-protocol/tests/client.rs @@ -310,7 +310,8 @@ fn messagechat_sendable_types_golden() { /// `SendAddonMessage` (reference `0x49f920`) sends `CMSG_MESSAGECHAT` on one of four lanes: `u32` /// type, `u32` language `LANG_ADDON`, then one cstring of prefix, TAB and message (`0x49f9b3`); -/// there is no prefix or target field. The receiver splits on the first TAB (`0x49a8d0`). +/// there is no prefix or target field. The receiver splits on the first TAB (`0x49a8d0`); vmangos +/// relays the TAB intact, as it skips `SanitizeChatMessage` for addon chat (`ChatHandler.cpp:49`). #[test] fn addon_message_bodies_golden() { assert_eq!( diff --git a/crates/benilla-protocol/tests/guild.rs b/crates/benilla-protocol/tests/guild.rs index 1cb3bd71..40d54d78 100644 --- a/crates/benilla-protocol/tests/guild.rs +++ b/crates/benilla-protocol/tests/guild.rs @@ -383,7 +383,7 @@ fn guild_roster_with_no_members_is_just_the_head() { } /// A viewer without `GR_RIGHT_VIEWOFFNOTE` gets `""` for every officer note (vmangos -/// `Guild/Guild.cpp:821`, `:844`): the cstring's NUL is still on the wire. +/// `Guild/Guild.cpp:819`, `:846`): the cstring's NUL is still on the wire. #[test] fn guild_roster_reads_the_empty_officer_notes_of_an_unprivileged_viewer() { let mut body = roster_head(2, "motd", "info", &[guild_rank_right::ALL, 0x0000_0003]); diff --git a/crates/benilla-protocol/tests/simple_packets.rs b/crates/benilla-protocol/tests/simple_packets.rs index 5ac6e1af..36bf42a9 100644 --- a/crates/benilla-protocol/tests/simple_packets.rs +++ b/crates/benilla-protocol/tests/simple_packets.rs @@ -309,7 +309,7 @@ fn death_arc_family_parses_and_decodes() { } } - // The movement-flag bits (vmangos `Objects/MovementInfo.h:25-62`). + // The movement-flag bits (vmangos `Objects/MovementInfo.h:28-62`). assert_eq!(MoveMode::Root.flag(), 0x0000_1000); assert_eq!(MoveMode::WaterWalk.flag(), 0x1000_0000); assert_eq!(MoveMode::FeatherFall.flag(), 0x2000_0000); diff --git a/crates/benilla-protocol/tests/spells.rs b/crates/benilla-protocol/tests/spells.rs index 7314dacc..232d4a1f 100644 --- a/crates/benilla-protocol/tests/spells.rs +++ b/crates/benilla-protocol/tests/spells.rs @@ -1031,7 +1031,7 @@ fn combat_log_wire_golden() { } } -/// Raw caster guid, u32 spellId, u32 count, raw guids (vmangos `Spell.cpp:4970-4997`); in the +/// Raw caster guid, u32 spellId, u32 count, raw guids (vmangos `Spell.cpp:4974-4997`); in the /// reference (`0x6e9820`) the only writer of the beams' chain-target array (`unit+0xd44`). #[test] fn spell_chain_targets_wire() { diff --git a/crates/benilla-protocol/tests/trainer.rs b/crates/benilla-protocol/tests/trainer.rs index b8319686..3e4c365e 100644 --- a/crates/benilla-protocol/tests/trainer.rs +++ b/crates/benilla-protocol/tests/trainer.rs @@ -189,7 +189,7 @@ fn trainer_buy_result_wire() { #[test] fn learned_and_superceded_spell_wire() { // SMSG_LEARNED_SPELL: u16 spellId + u16 actionBarSlot, the slot unused by the client and - // dropped (vmangos `Spell.cpp:175-179`). + // dropped (vmangos `Packets/Spell.cpp:175-179`). match messages::parse_server(messages::opcode::SMSG_LEARNED_SPELL, &hx("cb19aaaa")).unwrap() { ServerPacket::LearnedSpell { spell_id } => assert_eq!(spell_id, 6603), other => panic!("learned spell, got {}", other.name()), @@ -201,7 +201,7 @@ fn learned_and_superceded_spell_wire() { other => panic!("spell learned event, got {other:?}"), } - // SMSG_SUPERCEDED_SPELL: u16 oldSpellId + u16 newSpellId (vmangos `Spell.cpp:169-173`). + // SMSG_SUPERCEDED_SPELL: u16 oldSpellId + u16 newSpellId (vmangos `Packets/Spell.cpp:169-173`). match messages::parse_server(messages::opcode::SMSG_SUPERCEDED_SPELL, &hx("cb19cc19")).unwrap() { ServerPacket::SupercededSpell { diff --git a/docs/MAP.md b/docs/MAP.md index e94ece58..a06f1408 100644 --- a/docs/MAP.md +++ b/docs/MAP.md @@ -364,7 +364,7 @@ - `WOW_PARTICLE_DEPTHDUMP_BONES` — benilla-world/src/particles/depthdump.rs - `WOW_PARTICLE_FLAT` — benilla-world/src/particles/render.rs - `WOW_PARTICLE_NODEPTH` — benilla-world/src/particles/render.rs -- `WOW_PASS` — benilla-app/src/login/mod.rs, benilla-app/src/net.rs, benilla-app/src/run_mode.rs +- `WOW_PASS` — benilla-app/src/login/mod.rs, benilla-app/src/net.rs, benilla-app/src/run_mode.rs, benilla-protocol/examples/login_refusal_probe.rs, benilla-protocol/examples/park_probe.rs - `WOW_PERF_HUD` — benilla-app/src/perf/hud.rs - `WOW_PHASE` — benilla-app/src/capture/phase_probe.rs, benilla-app/src/dev.rs, benilla-world/src/bgwin.rs - `WOW_PHASE_AT` — benilla-app/src/capture/phase_probe.rs @@ -493,7 +493,7 @@ - `WOW_UNIT_VISUALS` — benilla-app/src/capture/probes/visual_census.rs, benilla-app/src/dev.rs - `WOW_UNIT_VISUALS_RADIUS` — benilla-app/src/capture/probes/visual_census.rs - `WOW_UPLOAD_BUDGET` — benilla-world/src/world_plugins.rs -- `WOW_USER` — benilla-app/src/login/mod.rs, benilla-app/src/net.rs, benilla-app/src/run_mode.rs +- `WOW_USER` — benilla-app/src/login/mod.rs, benilla-app/src/net.rs, benilla-app/src/run_mode.rs, benilla-protocol/examples/login_refusal_probe.rs, benilla-protocol/examples/park_probe.rs - `WOW_VIS_DUMP` — benilla-app/src/capture/probes/live_fps.rs - `WOW_VIS_TRACE` — benilla-world/src/model_render/visibility.rs - `WOW_VISTA_AT` — benilla-app/src/capture/mod.rs