diff --git a/gateway/src/world/benilla_tests/durable.rs b/gateway/src/world/benilla_tests/durable.rs index 1c8f5b0da..3d48a5cde 100644 --- a/gateway/src/world/benilla_tests/durable.rs +++ b/gateway/src/world/benilla_tests/durable.rs @@ -221,6 +221,56 @@ impl Client { } } +#[test] +#[ignore = "requires SpacetimeDB 2.7.1 and the Wasm toolchain"] +fn benilla_durable_target_selection_during_taxi_keeps_the_world_session_connected() { + let realm = Realm::start("benilla-taxi-selection"); + let (mut client, gateway) = realm.connect("TEST"); + client.enter_world(); + // Stage an active flight without a schedule so selection cannot race landing. + realm.standalone.assert_sql( + "INSERT INTO game_active_taxi_flight \ + (character_guid,path_id,source_node_id,destination_node_id,mount_display_id,fare,\ + current_node_index,started_micros) \ + VALUES (1,5090102,5090100,5090101,1147,25,0,1)", + ); + let flight = realm + .standalone + .query_rows("SELECT * FROM game_active_taxi_flight WHERE character_guid = 1"); + let money = realm + .standalone + .query_rows("SELECT money FROM game_world_entity WHERE guid = 1"); + + for target in [2u64, 0] { + client.send(opcode::CMSG_SET_SELECTION, &target.to_le_bytes()); + client.send(opcode::CMSG_PING, &messages::ping(7, 0)); + client.until("PONG after taxi target selection", |packet| { + matches!(packet, ServerPacket::Pong { sequence: 7 }) + }); + assert_eq!( + realm + .standalone + .query_rows("SELECT target_guid FROM game_world_entity WHERE guid = 1")[0] + ["target_guid"], + target.to_string(), + ); + assert_eq!( + realm + .standalone + .query_rows("SELECT * FROM game_active_taxi_flight WHERE character_guid = 1"), + flight, + ); + assert_eq!( + realm + .standalone + .query_rows("SELECT money FROM game_world_entity WHERE guid = 1"), + money, + ); + } + client.socket.shutdown(std::net::Shutdown::Both).unwrap(); + gateway.join().unwrap().unwrap(); +} + #[test] #[ignore = "requires SpacetimeDB 2.7.1 and the Wasm toolchain"] fn benilla_durable_created_character_appears_in_the_first_roster() { diff --git a/module/src/gw.rs b/module/src/gw.rs index 314188798..a8a32088a 100644 --- a/module/src/gw.rs +++ b/module/src/gw.rs @@ -627,8 +627,7 @@ pub fn gw_accept_group_invite( crate::actor::accept_group_invite(ctx, actor_guid) } -/// [`crate::world::set_target`] with the actor named by guid — `CMSG_SET_SELECTION`, second -/// hottest call after movement. +/// Record the Character's selection, including while a taxi flight controls movement. #[reducer] pub fn gw_set_target( ctx: &ReducerContext, @@ -637,8 +636,9 @@ pub fn gw_set_target( ) -> Result<(), String> { require_operator(ctx)?; let actor_guid = crate::account_ownership::require_actor(ctx, request_actor)?; - let player = actor(ctx, actor_guid)?; - crate::world::apply_set_target(ctx, player, target_guid) + let entity = + acting_entity_by_guid(ctx, actor_guid).ok_or_else(|| "mover not in world".to_string())?; + crate::world::apply_set_target(ctx, entity, target_guid) } /// [`crate::chat::apply_send_chat`] with the speaker named by guid — SAY/YELL/`/e`.