From b2926edf53ad8cf5718b4de1a2767eaa8a4156a2 Mon Sep 17 00:00:00 2001 From: Sam Sung <51686767+samwhosung@users.noreply.github.com> Date: Mon, 12 Oct 2026 12:46:31 +0700 Subject: [PATCH] Stock realm list and wizard; realm park cancels cleanly (#985) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Part 3b of the stock GlueXML (`WOW_GLUE_STOCK=1`): the stock `RealmList` and `RealmWizard` run on the reference's ten realm verbs (`0x46f480`). - The realm park is now a cancellable operation. Each dial carries the cancel generation it was asked under, so no Cancel is lost, and a status Cancel closes the logon (`0x5b3320`). - Change Realm with the world up drops the session first (`0x46b22b`). - The roster arm (`0x4724d0`) sets the chosen realm, or asks for the list when the roster is empty. - An empty realm list is shown, never dialled at the world port. - The native type sort puts PvP before RP. Deviation lines cover the re-dial's full logon, comparator ties, a missing Region row and the native close. Part of #856 and #834 Fixes #833 Fixes #974 Fixes #982 πŸ€– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 5.5 --- crates/benilla-app/src/capture/realm_list.rs | 5 +- crates/benilla-app/src/char_select/input.rs | 15 +- crates/benilla-app/src/login/mod.rs | 167 ++- crates/benilla-app/src/net.rs | 39 +- crates/benilla-app/src/net/io.rs | 481 ++++--- crates/benilla-app/src/net/io/cycle_tests.rs | 411 +++--- crates/benilla-app/src/net/io/fake.rs | 443 +++++++ crates/benilla-app/src/net/session.rs | 4 +- crates/benilla-app/src/realm_select/input.rs | 59 +- crates/benilla-app/src/realm_select/load.rs | 56 +- crates/benilla-app/src/realm_select/mod.rs | 143 +- crates/benilla-app/src/realm_select/screen.rs | 1 + crates/benilla-app/src/realm_select/smoke.rs | 26 +- crates/benilla-app/src/ui_script/glue_mgr.rs | 374 +++++- .../src/ui_script/glue_mgr_tests.rs | 469 ++++++- crates/benilla-protocol/src/events.rs | 10 +- crates/benilla-ui/src/script/glue.rs | 3 +- crates/benilla-ui/src/script/glue_core.rs | 18 +- crates/benilla-ui/src/script/glue_realm.rs | 1160 +++++++++++++++++ crates/benilla-ui/src/script/mod.rs | 9 +- .../src/script/tests/glue_surface.rs | 15 - 21 files changed, 3326 insertions(+), 582 deletions(-) create mode 100644 crates/benilla-app/src/net/io/fake.rs create mode 100644 crates/benilla-ui/src/script/glue_realm.rs diff --git a/crates/benilla-app/src/capture/realm_list.rs b/crates/benilla-app/src/capture/realm_list.rs index 270314f4..d2c39341 100644 --- a/crates/benilla-app/src/capture/realm_list.rs +++ b/crates/benilla-app/src/capture/realm_list.rs @@ -47,7 +47,10 @@ pub(super) fn seed_realm_list( } match *step { 0 => { - lists.write(crate::net::RealmListMessage { realms: fixture() }); + lists.write(crate::net::RealmListMessage { + realms: fixture(), + failed: false, + }); } 2 => crate::realm_select::open_over_char_select(&mut realms, &choice), 3.. => return, diff --git a/crates/benilla-app/src/char_select/input.rs b/crates/benilla-app/src/char_select/input.rs index c58f3008..fc15b8f5 100644 --- a/crates/benilla-app/src/char_select/input.rs +++ b/crates/benilla-app/src/char_select/input.rs @@ -198,6 +198,7 @@ mod tests { .insert_resource(CharPick(pick_tx)) .insert_resource(RealmChoice(realm_tx)) .add_message::() + .add_message::() .add_message::() .add_systems(PreUpdate, take_input); if list_first { @@ -226,11 +227,21 @@ mod tests { } else { "screen first" }; + assert!( + !app.world().resource::().shown, + "{order}: the list's Cancel ran" + ); assert!( realm_rx .try_iter() - .any(|r| matches!(r, RealmRequest::Abandon)), - "{order}: the list's Cancel ran" + .all(|r| matches!(r, RealmRequest::Refresh)), + "{order}: and over character select it closes nothing" + ); + assert!( + app.world() + .resource::>() + .is_empty(), + "{order}: nor ends the login" ); assert_eq!( *app.world().resource::>().get(), diff --git a/crates/benilla-app/src/login/mod.rs b/crates/benilla-app/src/login/mod.rs index 07c2acf7..fd117e21 100644 --- a/crates/benilla-app/src/login/mod.rs +++ b/crates/benilla-app/src/login/mod.rs @@ -180,16 +180,22 @@ impl Attempt<'_> { } } -/// What the stock glue screens ask of the login engine, past the glue manager's own guards -/// ([`crate::ui_script::glue_mgr`]). +/// What the glue screens ask of the login engine: the stock ones past the glue manager's own +/// guards ([`crate::ui_script::glue_mgr`]), and the native realm list's Cancel over login. #[derive(Message)] pub(crate) enum GlueLogin { /// `CGlueMgr::Login` (`0x46afb0`) reaching `ClientServices`' logon (`0x5ab4b0`): one attempt, - /// typed, with the screen's credentials. + /// typed, with the screen's credentials. It supersedes a logon still parked at the realm list, + /// as the reference starts the next logon whatever link the last one left. Submit { account: String, password: String }, - /// The status dialog's Cancel during the logon (`0x5b3320`) or the world connect (`0x5aaa50` - /// with `RESPONSE_CANCELLED`): the attempt in flight is dropped and nothing resubmits. + /// `CLoginMgr::Cancel` (`0x5b3320`): the status dialog's Cancel during the logon, and + /// `RealmListDialogCancelled` on the login screen. The attempt in flight is dropped, the + /// realmd link closes, and nothing resubmits. Abandon, + /// The status dialog's Cancel during the world connect, which completes it + /// `RESPONSE_CANCELLED` (`0x46b754`); the failure arm then drops the world socket alone + /// (`0x46befd`, `0x5ab1a0`), so the attempt in flight ends and the realmd link stays up. + CancelWorld, /// `DisconnectFromServer` (`0x46d340`): the world session dropped if there is one, then the /// logon cancelled, as select's Back drops the parked session. Disconnect, @@ -205,26 +211,22 @@ pub(crate) fn answer_glue( mut asks: MessageReader, mut attempt: Attempt, pick: Option>, + realm: Option>, state: Res>, time: Res