diff options
| author | mat <git@matdoes.dev> | 2025-09-28 13:10:04 -0545 |
|---|---|---|
| committer | mat <git@matdoes.dev> | 2025-09-28 13:10:04 -0545 |
| commit | 2c8b7c5c2c9297273abfba8f7743f1bc25f166b1 (patch) | |
| tree | 3d3aded400100c136287fa59293ce26c61644d00 /azalea-client/src/plugins | |
| parent | e2ed19c1ed92f0dccc881d835d9ac6e0f7f834c0 (diff) | |
| download | azalea-drasl-2c8b7c5c2c9297273abfba8f7743f1bc25f166b1.tar.xz | |
upgrade bevy to 0.17.0-rc.2
Diffstat (limited to 'azalea-client/src/plugins')
24 files changed, 315 insertions, 399 deletions
diff --git a/azalea-client/src/plugins/attack.rs b/azalea-client/src/plugins/attack.rs index 7d730bb7..47e45896 100644 --- a/azalea-client/src/plugins/attack.rs +++ b/azalea-client/src/plugins/attack.rs @@ -19,7 +19,7 @@ use crate::{ pub struct AttackPlugin; impl Plugin for AttackPlugin { fn build(&self, app: &mut App) { - app.add_event::<AttackEvent>() + app.add_message::<AttackEvent>() .add_systems( Update, handle_attack_event @@ -45,7 +45,7 @@ impl Plugin for AttackPlugin { impl Client { /// Attack the entity with the given id. pub fn attack(&self, entity: Entity) { - self.ecs.lock().send_event(AttackEvent { + self.ecs.lock().write_message(AttackEvent { entity: self.entity, target: entity, }); @@ -148,14 +148,14 @@ pub fn handle_attack_queued( /// Queues up an attack packet for next tick by inserting the [`AttackQueued`] /// component to our client. -#[derive(Event)] +#[derive(Message)] pub struct AttackEvent { /// Our client entity that will send the packets to attack. pub entity: Entity, /// The entity that will be attacked. pub target: Entity, } -pub fn handle_attack_event(mut events: EventReader<AttackEvent>, mut commands: Commands) { +pub fn handle_attack_event(mut events: MessageReader<AttackEvent>, mut commands: Commands) { for event in events.read() { commands.entity(event.entity).insert(AttackQueued { target: event.target, diff --git a/azalea-client/src/plugins/auto_reconnect.rs b/azalea-client/src/plugins/auto_reconnect.rs index 1391545f..bff72e5a 100644 --- a/azalea-client/src/plugins/auto_reconnect.rs +++ b/azalea-client/src/plugins/auto_reconnect.rs @@ -39,8 +39,8 @@ impl Plugin for AutoReconnectPlugin { pub fn start_rejoin_on_disconnect( mut commands: Commands, - mut disconnect_events: EventReader<DisconnectEvent>, - mut connection_failed_events: EventReader<ConnectionFailedEvent>, + mut disconnect_events: MessageReader<DisconnectEvent>, + mut connection_failed_events: MessageReader<ConnectionFailedEvent>, auto_reconnect_delay_res: Option<Res<AutoReconnectDelay>>, auto_reconnect_delay_query: Query<&AutoReconnectDelay>, ) { @@ -85,7 +85,7 @@ fn get_delay( pub fn rejoin_after_delay( mut commands: Commands, - mut join_events: EventWriter<StartJoinServerEvent>, + mut join_events: MessageWriter<StartJoinServerEvent>, query: Query<( Entity, &InternalReconnectAfter, diff --git a/azalea-client/src/plugins/chat/handler.rs b/azalea-client/src/plugins/chat/handler.rs index a289eb14..d71bcbd1 100644 --- a/azalea-client/src/plugins/chat/handler.rs +++ b/azalea-client/src/plugins/chat/handler.rs @@ -21,7 +21,7 @@ use crate::{Account, chat_signing::ChatSigningSession, packet::game::SendPacketE /// preserved if multiple chat messages and commands are sent at the same time. /// /// [`SendChatEvent`]: super::SendChatEvent -#[derive(Event)] +#[derive(Message)] pub struct SendChatKindEvent { pub entity: Entity, pub content: String, @@ -29,7 +29,7 @@ pub struct SendChatKindEvent { } pub fn handle_send_chat_kind_event( - mut events: EventReader<SendChatKindEvent>, + mut events: MessageReader<SendChatKindEvent>, mut commands: Commands, mut query: Query<(&Account, &mut ChatSigningSession)>, ) { diff --git a/azalea-client/src/plugins/chat/mod.rs b/azalea-client/src/plugins/chat/mod.rs index f8ef3251..098b6543 100644 --- a/azalea-client/src/plugins/chat/mod.rs +++ b/azalea-client/src/plugins/chat/mod.rs @@ -19,9 +19,9 @@ use crate::client::Client; pub struct ChatPlugin; impl Plugin for ChatPlugin { fn build(&self, app: &mut App) { - app.add_event::<SendChatEvent>() - .add_event::<SendChatKindEvent>() - .add_event::<ChatReceivedEvent>() + app.add_message::<SendChatEvent>() + .add_message::<SendChatKindEvent>() + .add_message::<ChatReceivedEvent>() .add_systems( Update, (handle_send_chat_event, handle_send_chat_kind_event).chain(), @@ -189,7 +189,7 @@ impl Client { /// handles checking whether the message is a command and using the /// proper packet for you, so you should use that instead. pub fn write_chat_packet(&self, message: &str) { - self.ecs.lock().send_event(SendChatKindEvent { + self.ecs.lock().write_message(SendChatKindEvent { entity: self.entity, content: message.to_string(), kind: ChatKind::Message, @@ -202,7 +202,7 @@ impl Client { /// You can also just use [`Client::chat`] and start your message with a `/` /// to send a command. pub fn write_command_packet(&self, command: &str) { - self.ecs.lock().send_event(SendChatKindEvent { + self.ecs.lock().write_message(SendChatKindEvent { entity: self.entity, content: command.to_string(), kind: ChatKind::Command, @@ -219,7 +219,7 @@ impl Client { /// # } /// ``` pub fn chat(&self, content: impl Into<String>) { - self.ecs.lock().send_event(SendChatEvent { + self.ecs.lock().write_message(SendChatEvent { entity: self.entity, content: content.into(), }); @@ -227,22 +227,22 @@ impl Client { } /// A client received a chat message packet. -#[derive(Event, Debug, Clone)] +#[derive(Message, Debug, Clone)] pub struct ChatReceivedEvent { pub entity: Entity, pub packet: ChatPacket, } /// Send a chat message (or command, if it starts with a slash) to the server. -#[derive(Event)] +#[derive(Message)] pub struct SendChatEvent { pub entity: Entity, pub content: String, } pub fn handle_send_chat_event( - mut events: EventReader<SendChatEvent>, - mut send_chat_kind_events: EventWriter<SendChatKindEvent>, + mut events: MessageReader<SendChatEvent>, + mut send_chat_kind_events: MessageWriter<SendChatKindEvent>, ) { for event in events.read() { if event.content.starts_with('/') { diff --git a/azalea-client/src/plugins/chunks.rs b/azalea-client/src/plugins/chunks.rs index ff4f8a53..f8d2c523 100644 --- a/azalea-client/src/plugins/chunks.rs +++ b/azalea-client/src/plugins/chunks.rs @@ -35,13 +35,13 @@ impl Plugin for ChunksPlugin { .before(InventorySet) .before(perform_respawn), ) - .add_event::<ReceiveChunkEvent>() - .add_event::<ChunkBatchStartEvent>() - .add_event::<ChunkBatchFinishedEvent>(); + .add_message::<ReceiveChunkEvent>() + .add_message::<ChunkBatchStartEvent>() + .add_message::<ChunkBatchFinishedEvent>(); } } -#[derive(Event)] +#[derive(Message)] pub struct ReceiveChunkEvent { pub entity: Entity, pub packet: ClientboundLevelChunkWithLight, @@ -54,18 +54,18 @@ pub struct ChunkBatchInfo { pub old_samples_weight: u32, } -#[derive(Event)] +#[derive(Message)] pub struct ChunkBatchStartEvent { pub entity: Entity, } -#[derive(Event)] +#[derive(Message)] pub struct ChunkBatchFinishedEvent { pub entity: Entity, pub batch_size: u32, } pub fn handle_receive_chunk_event( - mut events: EventReader<ReceiveChunkEvent>, + mut events: MessageReader<ReceiveChunkEvent>, mut query: Query<&InstanceHolder>, ) { for event in events.read() { @@ -132,7 +132,7 @@ impl ChunkBatchInfo { pub fn handle_chunk_batch_start_event( mut query: Query<&mut ChunkBatchInfo>, - mut events: EventReader<ChunkBatchStartEvent>, + mut events: MessageReader<ChunkBatchStartEvent>, ) { for event in events.read() { if let Ok(mut chunk_batch_info) = query.get_mut(event.entity) { @@ -143,7 +143,7 @@ pub fn handle_chunk_batch_start_event( pub fn handle_chunk_batch_finished_event( mut query: Query<&mut ChunkBatchInfo>, - mut events: EventReader<ChunkBatchFinishedEvent>, + mut events: MessageReader<ChunkBatchFinishedEvent>, mut commands: Commands, ) { for event in events.read() { diff --git a/azalea-client/src/plugins/client_information.rs b/azalea-client/src/plugins/client_information.rs index d30b5329..499b8ab5 100644 --- a/azalea-client/src/plugins/client_information.rs +++ b/azalea-client/src/plugins/client_information.rs @@ -60,11 +60,9 @@ impl Client { /// # } /// ``` pub async fn set_client_information(&self, client_information: ClientInformation) { - { - let mut ecs = self.ecs.lock(); - let mut client_information_mut = self.query::<&mut ClientInformation>(&mut ecs); - *client_information_mut = client_information.clone(); - } + self.query_self::<&mut ClientInformation, _>(|mut ci| { + *ci = client_information.clone(); + }); if self.logged_in() { debug!( diff --git a/azalea-client/src/plugins/connection.rs b/azalea-client/src/plugins/connection.rs index f439ac33..54966703 100644 --- a/azalea-client/src/plugins/connection.rs +++ b/azalea-client/src/plugins/connection.rs @@ -124,7 +124,7 @@ pub fn read_packets(ecs: &mut World) { } } - queued_packet_events.send_events(ecs); + queued_packet_events.write_messages(ecs); } fn poll_all_writer_tasks(mut conn_query: Query<&mut RawConnection>) { @@ -149,10 +149,10 @@ pub struct QueuedPacketEvents { game: Vec<ReceiveGamePacketEvent>, } impl QueuedPacketEvents { - fn send_events(&mut self, ecs: &mut World) { - ecs.send_event_batch(self.login.drain(..)); - ecs.send_event_batch(self.config.drain(..)); - ecs.send_event_batch(self.game.drain(..)); + fn write_messages(&mut self, ecs: &mut World) { + ecs.write_message_batch(self.login.drain(..)); + ecs.write_message_batch(self.config.drain(..)); + ecs.write_message_batch(self.game.drain(..)); } } diff --git a/azalea-client/src/plugins/disconnect.rs b/azalea-client/src/plugins/disconnect.rs index 3cb9e82a..95950ae9 100644 --- a/azalea-client/src/plugins/disconnect.rs +++ b/azalea-client/src/plugins/disconnect.rs @@ -19,7 +19,7 @@ use crate::{ pub struct DisconnectPlugin; impl Plugin for DisconnectPlugin { fn build(&self, app: &mut App) { - app.add_event::<DisconnectEvent>().add_systems( + app.add_message::<DisconnectEvent>().add_systems( PostUpdate, ( update_read_packets_task_running_component, @@ -45,7 +45,7 @@ impl Plugin for DisconnectPlugin { /// /// [`ConnectionFailedEvent`]: crate::join::ConnectionFailedEvent -#[derive(Event)] +#[derive(Message)] pub struct DisconnectEvent { pub entity: Entity, pub reason: Option<FormattedText>, @@ -82,7 +82,7 @@ pub struct RemoveOnDisconnectBundle { /// a [`DisconnectEvent`]. pub fn remove_components_from_disconnected_players( mut commands: Commands, - mut events: EventReader<DisconnectEvent>, + mut events: MessageReader<DisconnectEvent>, mut loaded_by_query: Query<&mut azalea_entity::LoadedBy>, ) { for DisconnectEvent { entity, reason } in events.read() { @@ -125,7 +125,7 @@ fn update_read_packets_task_running_component( #[allow(clippy::type_complexity)] fn disconnect_on_connection_dead( query: Query<(Entity, &IsConnectionAlive), (Changed<IsConnectionAlive>, With<LocalEntity>)>, - mut disconnect_events: EventWriter<DisconnectEvent>, + mut disconnect_events: MessageWriter<DisconnectEvent>, ) { for (entity, &is_connection_alive) in &query { if !*is_connection_alive { diff --git a/azalea-client/src/plugins/events.rs b/azalea-client/src/plugins/events.rs index 581a3e81..bc8a7a98 100644 --- a/azalea-client/src/plugins/events.rs +++ b/azalea-client/src/plugins/events.rs @@ -35,7 +35,7 @@ use crate::{ // use. // - Add the event struct in PacketPlugin::build // - (in the `impl Plugin for PacketPlugin`) -// - To get the event writer, you have to get an EventWriter<ThingEvent>. +// - To get the event writer, you have to get an MessageWriter<ThingEvent>. // Look at other packets in packet/game/mod.rs for examples. // // At this point, you've created a new ECS event. That's annoying for bots to @@ -195,7 +195,10 @@ pub fn spawn_listener( } } -pub fn chat_listener(query: Query<&LocalPlayerEvents>, mut events: EventReader<ChatReceivedEvent>) { +pub fn chat_listener( + query: Query<&LocalPlayerEvents>, + mut events: MessageReader<ChatReceivedEvent>, +) { for event in events.read() { if let Ok(local_player_events) = query.get(event.entity) { let _ = local_player_events.send(Event::Chat(event.packet.clone())); @@ -213,7 +216,7 @@ pub fn tick_listener(query: Query<&LocalPlayerEvents, With<InstanceName>>) { #[cfg(feature = "packet-event")] pub fn packet_listener( query: Query<&LocalPlayerEvents>, - mut events: EventReader<super::packet::game::ReceiveGamePacketEvent>, + mut events: MessageReader<super::packet::game::ReceiveGamePacketEvent>, ) { for event in events.read() { if let Ok(local_player_events) = query.get(event.entity) { @@ -224,7 +227,7 @@ pub fn packet_listener( pub fn add_player_listener( query: Query<&LocalPlayerEvents>, - mut events: EventReader<AddPlayerEvent>, + mut events: MessageReader<AddPlayerEvent>, ) { for event in events.read() { let local_player_events = query @@ -236,7 +239,7 @@ pub fn add_player_listener( pub fn update_player_listener( query: Query<&LocalPlayerEvents>, - mut events: EventReader<UpdatePlayerEvent>, + mut events: MessageReader<UpdatePlayerEvent>, ) { for event in events.read() { let local_player_events = query @@ -248,7 +251,7 @@ pub fn update_player_listener( pub fn remove_player_listener( query: Query<&LocalPlayerEvents>, - mut events: EventReader<RemovePlayerEvent>, + mut events: MessageReader<RemovePlayerEvent>, ) { for event in events.read() { let local_player_events = query @@ -258,7 +261,7 @@ pub fn remove_player_listener( } } -pub fn death_listener(query: Query<&LocalPlayerEvents>, mut events: EventReader<DeathEvent>) { +pub fn death_listener(query: Query<&LocalPlayerEvents>, mut events: MessageReader<DeathEvent>) { for event in events.read() { if let Ok(local_player_events) = query.get(event.entity) { let _ = local_player_events.send(Event::Death(event.packet.clone().map(|p| p.into()))); @@ -277,7 +280,7 @@ pub fn dead_component_listener(query: Query<&LocalPlayerEvents, Added<Dead>>) { pub fn keepalive_listener( query: Query<&LocalPlayerEvents>, - mut events: EventReader<KeepAliveEvent>, + mut events: MessageReader<KeepAliveEvent>, ) { for event in events.read() { let local_player_events = query @@ -289,7 +292,7 @@ pub fn keepalive_listener( pub fn disconnect_listener( query: Query<&LocalPlayerEvents>, - mut events: EventReader<DisconnectEvent>, + mut events: MessageReader<DisconnectEvent>, ) { for event in events.read() { if let Ok(local_player_events) = query.get(event.entity) { @@ -300,7 +303,7 @@ pub fn disconnect_listener( pub fn receive_chunk_listener( query: Query<&LocalPlayerEvents>, - mut events: EventReader<ReceiveChunkEvent>, + mut events: MessageReader<ReceiveChunkEvent>, ) { for event in events.read() { if let Ok(local_player_events) = query.get(event.entity) { diff --git a/azalea-client/src/plugins/interact/mod.rs b/azalea-client/src/plugins/interact/mod.rs index dc60ef66..b5defdf0 100644 --- a/azalea-client/src/plugins/interact/mod.rs +++ b/azalea-client/src/plugins/interact/mod.rs @@ -48,8 +48,7 @@ use crate::{ pub struct InteractPlugin; impl Plugin for InteractPlugin { fn build(&self, app: &mut App) { - app.add_event::<StartUseItemEvent>() - .add_event::<SwingArmEvent>() + app.add_message::<StartUseItemEvent>() .add_systems( Update, ( @@ -63,7 +62,6 @@ impl Plugin for InteractPlugin { update_hit_result_component .after(clamp_look_direction) .after(update_last_bounding_box), - handle_swing_arm_event, ) .after(InventorySet) .after(MoveEventsSet) @@ -89,7 +87,7 @@ impl Client { /// Note that this may trigger anticheats as it doesn't take into account /// whether you're actually looking at the block. pub fn block_interact(&self, position: BlockPos) { - self.ecs.lock().send_event(StartUseItemEvent { + self.ecs.lock().write_message(StartUseItemEvent { entity: self.entity, hand: InteractionHand::MainHand, force_block: Some(position), @@ -104,7 +102,7 @@ impl Client { /// If we're looking at a block or entity, then it will be clicked. Also see /// [`Client::block_interact`]. pub fn start_use_item(&self) { - self.ecs.lock().send_event(StartUseItemEvent { + self.ecs.lock().write_message(StartUseItemEvent { entity: self.entity, hand: InteractionHand::MainHand, force_block: None, @@ -209,7 +207,7 @@ impl BlockStatePredictionHandler { /// This event just inserts the [`StartUseItemQueued`] component on the given /// entity. #[doc(alias("right click"))] -#[derive(Event)] +#[derive(Message)] pub struct StartUseItemEvent { pub entity: Entity, pub hand: InteractionHand, @@ -218,7 +216,7 @@ pub struct StartUseItemEvent { } pub fn handle_start_use_item_event( mut commands: Commands, - mut events: EventReader<StartUseItemEvent>, + mut events: MessageReader<StartUseItemEvent>, ) { for event in events.read() { commands.entity(event.entity).insert(StartUseItemQueued { @@ -427,23 +425,18 @@ pub fn can_use_game_master_blocks( /// Swing your arm. This is purely a visual effect and won't interact with /// anything in the world. -#[derive(Event, Clone, Debug)] +#[derive(EntityEvent, Clone, Debug)] pub struct SwingArmEvent { pub entity: Entity, } -pub fn handle_swing_arm_trigger(trigger: Trigger<SwingArmEvent>, mut commands: Commands) { +pub fn handle_swing_arm_trigger(swing_arm: On<SwingArmEvent>, mut commands: Commands) { commands.trigger(SendPacketEvent::new( - trigger.event().entity, + swing_arm.entity, ServerboundSwing { hand: InteractionHand::MainHand, }, )); } -pub fn handle_swing_arm_event(mut events: EventReader<SwingArmEvent>, mut commands: Commands) { - for event in events.read() { - commands.trigger(event.clone()); - } -} #[allow(clippy::type_complexity)] fn update_attributes_for_held_item( diff --git a/azalea-client/src/plugins/inventory.rs b/azalea-client/src/plugins/inventory.rs index 968a805b..448f9e95 100644 --- a/azalea-client/src/plugins/inventory.rs +++ b/azalea-client/src/plugins/inventory.rs @@ -28,22 +28,10 @@ use crate::{Client, packet::game::SendPacketEvent, respawn::perform_respawn}; pub struct InventoryPlugin; impl Plugin for InventoryPlugin { fn build(&self, app: &mut App) { - app.add_event::<ClientsideCloseContainerEvent>() - .add_event::<MenuOpenedEvent>() - .add_event::<CloseContainerEvent>() - .add_event::<ContainerClickEvent>() - .add_event::<SetContainerContentEvent>() - .add_event::<SetSelectedHotbarSlotEvent>() + app.add_message::<SetSelectedHotbarSlotEvent>() .add_systems( Update, - ( - handle_set_selected_hotbar_slot_event, - handle_menu_opened_event, - handle_container_click_event, - handle_container_close_event, - handle_client_side_close_container_event, - ) - .chain() + handle_set_selected_hotbar_slot_event .in_set(InventorySet) .before(perform_respawn), ) @@ -53,6 +41,7 @@ impl Plugin for InventoryPlugin { ) .add_observer(handle_client_side_close_container_trigger) .add_observer(handle_menu_opened_trigger) + .add_observer(handle_container_close_event) .add_observer(handle_set_container_content_trigger); } } @@ -64,9 +53,7 @@ impl Client { /// Return the menu that is currently open. If no menu is open, this will /// have the player's inventory. pub fn menu(&self) -> Menu { - let mut ecs = self.ecs.lock(); - let inventory = self.query::<&Inventory>(&mut ecs); - inventory.menu().clone() + self.query_self::<&Inventory, _>(|inv| inv.menu().clone()) } /// Returns the index of the hotbar slot that's currently selected. @@ -77,15 +64,17 @@ impl Client { /// /// You can use [`Self::set_selected_hotbar_slot`] to change it. pub fn selected_hotbar_slot(&self) -> u8 { - let mut ecs = self.ecs.lock(); - let inventory = self.query::<&Inventory>(&mut ecs); - inventory.selected_hotbar_slot + self.query_self::<&Inventory, _>(|inv| inv.selected_hotbar_slot) } /// Update the selected hotbar slot index. /// /// This will run next `Update`, so you might want to call /// `bot.wait_updates(1)` after calling this if you're using `azalea`. + /// + /// # Panics + /// + /// This will panic if `new_hotbar_slot_index` is not in the range 0..=8. pub fn set_selected_hotbar_slot(&self, new_hotbar_slot_index: u8) { assert!( new_hotbar_slot_index < 9, @@ -93,7 +82,7 @@ impl Client { ); let mut ecs = self.ecs.lock(); - ecs.send_event(SetSelectedHotbarSlotEvent { + ecs.write_message(SetSelectedHotbarSlotEvent { entity: self.entity, slot: new_hotbar_slot_index, }); @@ -736,30 +725,25 @@ impl Default for Inventory { /// To watch for the menu being closed, you could use /// [`ClientsideCloseContainerEvent`]. To close it manually, use /// [`CloseContainerEvent`]. -#[derive(Event, Debug, Clone)] +#[derive(EntityEvent, Debug, Clone)] pub struct MenuOpenedEvent { pub entity: Entity, pub window_id: i32, pub menu_type: MenuKind, pub title: FormattedText, } -fn handle_menu_opened_trigger(event: Trigger<MenuOpenedEvent>, mut query: Query<&mut Inventory>) { +fn handle_menu_opened_trigger(event: On<MenuOpenedEvent>, mut query: Query<&mut Inventory>) { let mut inventory = query.get_mut(event.entity).unwrap(); inventory.id = event.window_id; inventory.container_menu = Some(Menu::from_kind(event.menu_type)); inventory.container_menu_title = Some(event.title.clone()); } -pub fn handle_menu_opened_event(mut events: EventReader<MenuOpenedEvent>, mut commands: Commands) { - for event in events.read() { - commands.trigger(event.clone()); - } -} /// Tell the server that we want to close a container. /// /// Note that this is also sent when the client closes its own inventory, even /// though there is no packet for opening its inventory. -#[derive(Event)] +#[derive(EntityEvent)] pub struct CloseContainerEvent { pub entity: Entity, /// The ID of the container to close. 0 for the player's inventory. If this @@ -767,31 +751,28 @@ pub struct CloseContainerEvent { pub id: i32, } fn handle_container_close_event( - query: Query<(Entity, &Inventory)>, - mut events: EventReader<CloseContainerEvent>, - mut client_side_events: EventWriter<ClientsideCloseContainerEvent>, + close_container: On<CloseContainerEvent>, mut commands: Commands, + query: Query<(Entity, &Inventory)>, ) { - for event in events.read() { - let (entity, inventory) = query.get(event.entity).unwrap(); - if event.id != inventory.id { - warn!( - "Tried to close container with ID {}, but the current container ID is {}", - event.id, inventory.id - ); - continue; - } - - commands.trigger(SendPacketEvent::new( - entity, - ServerboundContainerClose { - container_id: inventory.id, - }, - )); - client_side_events.write(ClientsideCloseContainerEvent { - entity: event.entity, - }); + let (entity, inventory) = query.get(close_container.entity).unwrap(); + if close_container.id != inventory.id { + warn!( + "Tried to close container with ID {}, but the current container ID is {}", + close_container.id, inventory.id + ); + return; } + + commands.trigger(SendPacketEvent::new( + entity, + ServerboundContainerClose { + container_id: inventory.id, + }, + )); + commands.trigger(ClientsideCloseContainerEvent { + entity: close_container.entity, + }); } /// A Bevy trigger that's fired when our client closed a container. @@ -802,12 +783,12 @@ fn handle_container_close_event( /// /// If you want to watch for a container being opened, you should use /// [`MenuOpenedEvent`]. -#[derive(Event, Clone)] +#[derive(EntityEvent, Clone)] pub struct ClientsideCloseContainerEvent { pub entity: Entity, } pub fn handle_client_side_close_container_trigger( - event: Trigger<ClientsideCloseContainerEvent>, + event: On<ClientsideCloseContainerEvent>, mut query: Query<&mut Inventory>, ) { let mut inventory = query.get_mut(event.entity).unwrap(); @@ -838,126 +819,120 @@ pub fn handle_client_side_close_container_trigger( inventory.id = 0; inventory.container_menu_title = None; } -pub fn handle_client_side_close_container_event( - mut commands: Commands, - mut events: EventReader<ClientsideCloseContainerEvent>, -) { - for event in events.read() { - commands.trigger(event.clone()); - } -} -#[derive(Event, Debug)] +#[derive(EntityEvent, Debug)] pub struct ContainerClickEvent { pub entity: Entity, pub window_id: i32, pub operation: ClickOperation, } pub fn handle_container_click_event( + mut commands: Commands, + container_click: On<ContainerClickEvent>, mut query: Query<( Entity, &mut Inventory, Option<&PlayerAbilities>, &InstanceName, )>, - mut events: EventReader<ContainerClickEvent>, - mut commands: Commands, instance_container: Res<InstanceContainer>, ) { - for event in events.read() { - let (entity, mut inventory, player_abilities, instance_name) = - query.get_mut(event.entity).unwrap(); - if inventory.id != event.window_id { - error!( - "Tried to click container with ID {}, but the current container ID is {}. Click packet won't be sent.", - event.window_id, inventory.id - ); - continue; - } - - let Some(instance) = instance_container.get(instance_name) else { - continue; - }; - - let old_slots = inventory.menu().slots(); - inventory.simulate_click( - &event.operation, - player_abilities.unwrap_or(&PlayerAbilities::default()), + let (entity, mut inventory, player_abilities, instance_name) = + query.get_mut(container_click.entity).unwrap(); + if inventory.id != container_click.window_id { + error!( + "Tried to click container with ID {}, but the current container ID is {}. Click packet won't be sent.", + container_click.window_id, inventory.id ); - let new_slots = inventory.menu().slots(); + return; + } - let registry_holder = &instance.read().registries; - - // see which slots changed after clicking and put them in the map the server - // uses this to check if we desynced - let mut changed_slots: IndexMap<u16, HashedStack> = IndexMap::new(); - for (slot_index, old_slot) in old_slots.iter().enumerate() { - let new_slot = &new_slots[slot_index]; - if old_slot != new_slot { - changed_slots.insert( - slot_index as u16, - HashedStack::from_item_stack(new_slot, registry_holder), - ); - } - } + let Some(instance) = instance_container.get(instance_name) else { + return; + }; - commands.trigger(SendPacketEvent::new( - entity, - ServerboundContainerClick { - container_id: event.window_id, - state_id: inventory.state_id, - slot_num: event.operation.slot_num().map(|n| n as i16).unwrap_or(-999), - button_num: event.operation.button_num(), - click_type: event.operation.click_type(), - changed_slots, - carried_item: HashedStack::from_item_stack(&inventory.carried, registry_holder), - }, - )); + let old_slots = inventory.menu().slots(); + inventory.simulate_click( + &container_click.operation, + player_abilities.unwrap_or(&PlayerAbilities::default()), + ); + let new_slots = inventory.menu().slots(); + + let registry_holder = &instance.read().registries; + + // see which slots changed after clicking and put them in the map the server + // uses this to check if we desynced + let mut changed_slots: IndexMap<u16, HashedStack> = IndexMap::new(); + for (slot_index, old_slot) in old_slots.iter().enumerate() { + let new_slot = &new_slots[slot_index]; + if old_slot != new_slot { + changed_slots.insert( + slot_index as u16, + HashedStack::from_item_stack(new_slot, registry_holder), + ); + } } + + commands.trigger(SendPacketEvent::new( + entity, + ServerboundContainerClick { + container_id: container_click.window_id, + state_id: inventory.state_id, + slot_num: container_click + .operation + .slot_num() + .map(|n| n as i16) + .unwrap_or(-999), + button_num: container_click.operation.button_num(), + click_type: container_click.operation.click_type(), + changed_slots, + carried_item: HashedStack::from_item_stack(&inventory.carried, registry_holder), + }, + )); } /// Sent from the server when the contents of a container are replaced. /// /// Usually triggered by the `ContainerSetContent` packet. -#[derive(Event)] +#[derive(EntityEvent)] pub struct SetContainerContentEvent { pub entity: Entity, pub slots: Vec<ItemStack>, pub container_id: i32, } pub fn handle_set_container_content_trigger( - event: Trigger<SetContainerContentEvent>, + set_container_content: On<SetContainerContentEvent>, mut query: Query<&mut Inventory>, ) { - let mut inventory = query.get_mut(event.entity).unwrap(); + let mut inventory = query.get_mut(set_container_content.entity).unwrap(); - if event.container_id != inventory.id { + if set_container_content.container_id != inventory.id { warn!( "Got SetContainerContentEvent for container with ID {}, but the current container ID is {}", - event.container_id, inventory.id + set_container_content.container_id, inventory.id ); return; } let menu = inventory.menu_mut(); - for (i, slot) in event.slots.iter().enumerate() { + for (i, slot) in set_container_content.slots.iter().enumerate() { if let Some(slot_mut) = menu.slot_mut(i) { *slot_mut = slot.clone(); } } } -/// An ECS event to switch our hand to a different hotbar slot. +/// An ECS message to switch our hand to a different hotbar slot. /// /// This is equivalent to using the scroll wheel or number keys in Minecraft. -#[derive(Event)] +#[derive(Message)] pub struct SetSelectedHotbarSlotEvent { pub entity: Entity, /// The hotbar slot to select. This should be in the range 0..=8. pub slot: u8, } pub fn handle_set_selected_hotbar_slot_event( - mut events: EventReader<SetSelectedHotbarSlotEvent>, + mut events: MessageReader<SetSelectedHotbarSlotEvent>, mut query: Query<&mut Inventory>, ) { for event in events.read() { diff --git a/azalea-client/src/plugins/join.rs b/azalea-client/src/plugins/join.rs index ed2d6ed3..b9878370 100644 --- a/azalea-client/src/plugins/join.rs +++ b/azalea-client/src/plugins/join.rs @@ -30,8 +30,8 @@ use crate::{ pub struct JoinPlugin; impl Plugin for JoinPlugin { fn build(&self, app: &mut App) { - app.add_event::<StartJoinServerEvent>() - .add_event::<ConnectionFailedEvent>() + app.add_message::<StartJoinServerEvent>() + .add_message::<ConnectionFailedEvent>() .add_systems( Update, ( @@ -47,7 +47,7 @@ impl Plugin for JoinPlugin { /// /// This won't do anything if a client with the Account UUID is already /// connected to the server. -#[derive(Event, Debug)] +#[derive(Message, Debug)] pub struct StartJoinServerEvent { pub account: Account, pub connect_opts: ConnectOpts, @@ -74,7 +74,7 @@ pub struct ConnectOpts { /// This isn't sent if we're kicked later, see [`DisconnectEvent`]. /// /// [`DisconnectEvent`]: crate::disconnect::DisconnectEvent -#[derive(Event)] +#[derive(Message)] pub struct ConnectionFailedEvent { pub entity: Entity, pub error: ConnectionError, @@ -82,7 +82,7 @@ pub struct ConnectionFailedEvent { pub fn handle_start_join_server_event( mut commands: Commands, - mut events: EventReader<StartJoinServerEvent>, + mut events: MessageReader<StartJoinServerEvent>, mut entity_uuid_index: ResMut<EntityUuidIndex>, connection_query: Query<&RawConnection>, ) { @@ -184,7 +184,7 @@ pub struct CreateConnectionTask(pub Task<Result<LoginConn, ConnectionError>>); pub fn poll_create_connection_task( mut commands: Commands, mut query: Query<(Entity, &mut CreateConnectionTask, &Account)>, - mut connection_failed_events: EventWriter<ConnectionFailedEvent>, + mut connection_failed_events: MessageWriter<ConnectionFailedEvent>, ) { for (entity, mut task, account) in query.iter_mut() { if let Some(poll_res) = future::block_on(future::poll_once(&mut task.0)) { diff --git a/azalea-client/src/plugins/login.rs b/azalea-client/src/plugins/login.rs index 05e45cae..25919c8c 100644 --- a/azalea-client/src/plugins/login.rs +++ b/azalea-client/src/plugins/login.rs @@ -23,12 +23,12 @@ impl Plugin for LoginPlugin { } } -fn handle_receive_hello_event(trigger: Trigger<ReceiveHelloEvent>, mut commands: Commands) { +fn handle_receive_hello_event(receive_hello: On<ReceiveHelloEvent>, mut commands: Commands) { let task_pool = IoTaskPool::get(); - let account = trigger.account.clone(); - let packet = trigger.packet.clone(); - let player = trigger.target(); + let account = receive_hello.account.clone(); + let packet = receive_hello.packet.clone(); + let player = receive_hello.entity; let task = task_pool.spawn(auth_with_account(account, packet)); commands.entity(player).insert(AuthTask(task)); @@ -149,7 +149,7 @@ pub async fn auth_with_account( pub fn reply_to_custom_queries( mut commands: Commands, - mut events: EventReader<ReceiveCustomQueryEvent>, + mut events: MessageReader<ReceiveCustomQueryEvent>, ) { for event in events.read() { trace!("Maybe replying to custom query: {event:?}"); diff --git a/azalea-client/src/plugins/mining.rs b/azalea-client/src/plugins/mining.rs index e42ea866..b4f8adbe 100644 --- a/azalea-client/src/plugins/mining.rs +++ b/azalea-client/src/plugins/mining.rs @@ -26,11 +26,10 @@ use crate::{ pub struct MiningPlugin; impl Plugin for MiningPlugin { fn build(&self, app: &mut App) { - app.add_event::<StartMiningBlockEvent>() - .add_event::<FinishMiningBlockEvent>() - .add_event::<StopMiningBlockEvent>() - .add_event::<MineBlockProgressEvent>() - .add_event::<AttackBlockEvent>() + app.add_message::<StartMiningBlockEvent>() + .add_message::<StopMiningBlockEvent>() + .add_message::<MineBlockProgressEvent>() + .add_message::<AttackBlockEvent>() .add_systems( GameTick, ( @@ -57,8 +56,7 @@ impl Plugin for MiningPlugin { .after(MoveEventsSet) .after(azalea_entity::update_fluid_on_eyes) .after(crate::interact::pick::update_hit_result_component) - .after(crate::attack::handle_attack_event) - .before(crate::interact::handle_swing_arm_event), + .after(crate::attack::handle_attack_event), ) .add_observer(handle_finish_mining_block_observer); } @@ -72,7 +70,7 @@ impl Client { pub fn start_mining(&self, position: BlockPos) { let mut ecs = self.ecs.lock(); - ecs.send_event(StartMiningBlockEvent { + ecs.write_message(StartMiningBlockEvent { entity: self.entity, position, }); @@ -111,8 +109,8 @@ fn handle_auto_mine( ), With<LeftClickMine>, >, - mut start_mining_block_event: EventWriter<StartMiningBlockEvent>, - mut stop_mining_block_event: EventWriter<StopMiningBlockEvent>, + mut start_mining_block_event: MessageWriter<StartMiningBlockEvent>, + mut stop_mining_block_event: MessageWriter<StopMiningBlockEvent>, ) { for ( hit_result_component, @@ -161,14 +159,14 @@ pub struct Mining { /// /// If we're looking at the block then the correct direction will be used, /// otherwise it'll be [`Direction::Down`]. -#[derive(Event, Debug)] +#[derive(Message, Debug)] pub struct StartMiningBlockEvent { pub entity: Entity, pub position: BlockPos, } fn handle_start_mining_block_event( mut commands: Commands, - mut events: EventReader<StartMiningBlockEvent>, + mut events: MessageReader<StartMiningBlockEvent>, mut query: Query<&HitResultComponent>, ) { for event in events.read() { @@ -207,8 +205,8 @@ pub struct MiningQueued { #[allow(clippy::too_many_arguments, clippy::type_complexity)] pub fn handle_mining_queued( mut commands: Commands, - mut attack_block_events: EventWriter<AttackBlockEvent>, - mut mine_block_progress_events: EventWriter<MineBlockProgressEvent>, + mut attack_block_events: MessageWriter<AttackBlockEvent>, + mut mine_block_progress_events: MessageWriter<MineBlockProgressEvent>, query: Query<( Entity, &MiningQueued, @@ -269,12 +267,10 @@ pub fn handle_mining_queued( seq: sequence_number.start_predicting(), }, )); - commands.trigger_targets( - FinishMiningBlockEvent { - position: mining_queued.position, - }, + commands.trigger(FinishMiningBlockEvent { entity, - ); + position: mining_queued.position, + }); **mine_delay = 5; commands.trigger(SwingArmEvent { entity }); } else if mining.is_none() @@ -328,12 +324,10 @@ pub fn handle_mining_queued( ) >= 1. { // block was broken instantly (instamined) - commands.trigger_targets( - FinishMiningBlockEvent { - position: mining_queued.position, - }, + commands.trigger(FinishMiningBlockEvent { entity, - ); + position: mining_queued.position, + }); } else { let mining = Mining { pos: mining_queued.position, @@ -369,7 +363,7 @@ pub fn handle_mining_queued( } } -#[derive(Event)] +#[derive(Message)] pub struct MineBlockProgressEvent { pub entity: Entity, pub position: BlockPos, @@ -378,7 +372,7 @@ pub struct MineBlockProgressEvent { /// A player left clicked on a block, used for stuff like interacting with note /// blocks. -#[derive(Event)] +#[derive(Message)] pub struct AttackBlockEvent { pub entity: Entity, pub position: BlockPos, @@ -441,13 +435,14 @@ pub struct MineBlockPos(pub Option<BlockPos>); pub struct MineItem(pub ItemStack); /// A trigger that's sent when we completed mining a block. -#[derive(Event)] +#[derive(EntityEvent)] pub struct FinishMiningBlockEvent { + pub entity: Entity, pub position: BlockPos, } pub fn handle_finish_mining_block_observer( - trigger: Trigger<FinishMiningBlockEvent>, + finish_mining_block: On<FinishMiningBlockEvent>, mut query: Query<( &InstanceName, &LocalGameMode, @@ -459,7 +454,7 @@ pub fn handle_finish_mining_block_observer( )>, instances: Res<InstanceContainer>, ) { - let event = trigger.event(); + let event = finish_mining_block.event(); let ( instance_name, @@ -469,7 +464,7 @@ pub fn handle_finish_mining_block_observer( permission_level, player_pos, mut prediction_handler, - ) = query.get_mut(trigger.target()).unwrap(); + ) = query.get_mut(finish_mining_block.entity).unwrap(); let instance_lock = instances.get(instance_name).unwrap(); let instance = instance_lock.read(); if check_is_interaction_restricted(&instance, event.position, &game_mode.current, inventory) { @@ -515,14 +510,14 @@ pub fn handle_finish_mining_block_observer( } /// Abort mining a block. -#[derive(Event)] +#[derive(Message)] pub struct StopMiningBlockEvent { pub entity: Entity, } pub fn handle_stop_mining_block_event( - mut events: EventReader<StopMiningBlockEvent>, + mut events: MessageReader<StopMiningBlockEvent>, mut commands: Commands, - mut mine_block_progress_events: EventWriter<MineBlockProgressEvent>, + mut mine_block_progress_events: MessageWriter<MineBlockProgressEvent>, mut query: Query<(&MineBlockPos, &mut MineProgress)>, ) { for event in events.read() { @@ -567,7 +562,7 @@ pub fn continue_mining_block( &mut BlockStatePredictionHandler, )>, mut commands: Commands, - mut mine_block_progress_events: EventWriter<MineBlockProgressEvent>, + mut mine_block_progress_events: MessageWriter<MineBlockProgressEvent>, instances: Res<InstanceContainer>, ) { for ( @@ -603,12 +598,10 @@ pub fn continue_mining_block( seq: prediction_handler.start_predicting(), }, )); - commands.trigger_targets( - FinishMiningBlockEvent { - position: mining.pos, - }, + commands.trigger(FinishMiningBlockEvent { entity, - ); + position: mining.pos, + }); commands.trigger(SwingArmEvent { entity }); } else if mining.force || is_same_mining_target( @@ -648,12 +641,10 @@ pub fn continue_mining_block( // repeatedly inserts MiningQueued commands.entity(entity).remove::<(Mining, MiningQueued)>(); trace!("finished mining block at {:?}", mining.pos); - commands.trigger_targets( - FinishMiningBlockEvent { - position: mining.pos, - }, + commands.trigger(FinishMiningBlockEvent { entity, - ); + position: mining.pos, + }); commands.trigger(SendPacketEvent::new( entity, ServerboundPlayerAction { diff --git a/azalea-client/src/plugins/movement.rs b/azalea-client/src/plugins/movement.rs index 48e7ecea..c76158c5 100644 --- a/azalea-client/src/plugins/movement.rs +++ b/azalea-client/src/plugins/movement.rs @@ -65,9 +65,9 @@ pub struct MovementPlugin; impl Plugin for MovementPlugin { fn build(&self, app: &mut App) { - app.add_event::<StartWalkEvent>() - .add_event::<StartSprintEvent>() - .add_event::<KnockbackEvent>() + app.add_message::<StartWalkEvent>() + .add_message::<StartSprintEvent>() + .add_message::<KnockbackEvent>() .add_systems( Update, (handle_sprint, handle_walk, handle_knockback) @@ -105,9 +105,7 @@ impl Client { /// If you're making a realistic client, calling this function every tick is /// recommended. pub fn set_jumping(&self, jumping: bool) { - let mut ecs = self.ecs.lock(); - let mut jumping_mut = self.query::<&mut Jumping>(&mut ecs); - **jumping_mut = jumping; + self.query_self::<&mut Jumping, _>(|mut j| **j = jumping); } /// Returns whether the player will try to jump next tick. @@ -116,18 +114,14 @@ impl Client { } pub fn set_crouching(&self, crouching: bool) { - let mut ecs = self.ecs.lock(); - let mut physics_state = self.query::<&mut PhysicsState>(&mut ecs); - physics_state.trying_to_crouch = crouching; + self.query_self::<&mut PhysicsState, _>(|mut p| p.trying_to_crouch = crouching); } /// Whether the client is currently trying to sneak. /// /// You may want to check the [`Pose`] instead. pub fn crouching(&self) -> bool { - let mut ecs = self.ecs.lock(); - let physics_state = self.query::<&PhysicsState>(&mut ecs); - physics_state.trying_to_crouch + self.query_self::<&PhysicsState, _>(|p| p.trying_to_crouch) } /// Sets the direction the client is looking. `y_rot` is yaw (looking to the @@ -135,10 +129,9 @@ impl Client { /// numbers from the vanilla f3 screen. /// `y_rot` goes from -180 to 180, and `x_rot` goes from -90 to 90. pub fn set_direction(&self, y_rot: f32, x_rot: f32) { - let mut ecs = self.ecs.lock(); - let mut look_direction = self.query::<&mut LookDirection>(&mut ecs); - - look_direction.update(LookDirection::new(y_rot, x_rot)); + self.query_self::<&mut LookDirection, _>(|mut ld| { + ld.update(LookDirection::new(y_rot, x_rot)); + }); } /// Returns the direction the client is looking. The first value is the y @@ -557,7 +550,7 @@ impl Client { /// ``` pub fn walk(&self, direction: WalkDirection) { let mut ecs = self.ecs.lock(); - ecs.send_event(StartWalkEvent { + ecs.write_message(StartWalkEvent { entity: self.entity, direction, }); @@ -580,7 +573,7 @@ impl Client { /// ``` pub fn sprint(&self, direction: SprintDirection) { let mut ecs = self.ecs.lock(); - ecs.send_event(StartSprintEvent { + ecs.write_message(StartSprintEvent { entity: self.entity, direction, }); @@ -591,7 +584,7 @@ impl Client { /// non-local entities. /// /// To stop walking or sprinting, send this event with `WalkDirection::None`. -#[derive(Event, Debug)] +#[derive(Message, Debug)] pub struct StartWalkEvent { pub entity: Entity, pub direction: WalkDirection, @@ -600,7 +593,7 @@ pub struct StartWalkEvent { /// The system that makes the player start walking when they receive a /// [`StartWalkEvent`]. pub fn handle_walk( - mut events: EventReader<StartWalkEvent>, + mut events: MessageReader<StartWalkEvent>, mut query: Query<(&mut PhysicsState, &mut Sprinting, &mut Attributes)>, ) { for event in events.read() { @@ -615,7 +608,7 @@ pub fn handle_walk( /// An event sent when the client starts sprinting. This does not get sent for /// non-local entities. -#[derive(Event)] +#[derive(Message)] pub struct StartSprintEvent { pub entity: Entity, pub direction: SprintDirection, @@ -624,7 +617,7 @@ pub struct StartSprintEvent { /// [`StartSprintEvent`]. pub fn handle_sprint( mut query: Query<&mut PhysicsState>, - mut events: EventReader<StartSprintEvent>, + mut events: MessageReader<StartSprintEvent>, ) { for event in events.read() { if let Ok(mut physics_state) = query.get_mut(event.entity) { @@ -673,7 +666,7 @@ fn has_enough_impulse_to_start_sprinting(physics_state: &PhysicsState) -> bool { /// `KnockbackKind::Set` is used for normal knockback and `KnockbackKind::Add` /// is used for explosions, but some servers (notably Hypixel) use explosions /// for knockback. -#[derive(Event)] +#[derive(Message)] pub struct KnockbackEvent { pub entity: Entity, pub knockback: KnockbackType, @@ -684,7 +677,7 @@ pub enum KnockbackType { Add(Vec3), } -pub fn handle_knockback(mut query: Query<&mut Physics>, mut events: EventReader<KnockbackEvent>) { +pub fn handle_knockback(mut query: Query<&mut Physics>, mut events: MessageReader<KnockbackEvent>) { for event in events.read() { if let Ok(mut physics) = query.get_mut(event.entity) { match event.knockback { diff --git a/azalea-client/src/plugins/packet/config/events.rs b/azalea-client/src/plugins/packet/config/events.rs index a9237e75..be5cfdb1 100644 --- a/azalea-client/src/plugins/packet/config/events.rs +++ b/azalea-client/src/plugins/packet/config/events.rs @@ -9,7 +9,7 @@ use tracing::{debug, error}; use crate::{InConfigState, connection::RawConnection}; -#[derive(Event, Debug, Clone)] +#[derive(Message, Debug, Clone)] pub struct ReceiveConfigPacketEvent { /// The client entity that received the packet. pub entity: Entity, @@ -19,8 +19,9 @@ pub struct ReceiveConfigPacketEvent { /// An event for sending a packet to the server while we're in the /// `configuration` state. -#[derive(Event, Clone)] +#[derive(EntityEvent, Clone)] pub struct SendConfigPacketEvent { + #[event_target] pub sent_by: Entity, pub packet: ServerboundConfigPacket, } @@ -32,41 +33,33 @@ impl SendConfigPacketEvent { } pub fn handle_outgoing_packets_observer( - trigger: Trigger<SendConfigPacketEvent>, + send_config_packet: On<SendConfigPacketEvent>, mut query: Query<(&mut RawConnection, Option<&InConfigState>)>, ) { - let event = trigger.event(); - if let Ok((mut raw_conn, in_configuration_state)) = query.get_mut(event.sent_by) { + if let Ok((mut raw_conn, in_configuration_state)) = query.get_mut(send_config_packet.sent_by) { if in_configuration_state.is_none() { error!( "Tried to send a configuration packet {:?} while not in configuration state", - event.packet + send_config_packet.packet ); return; } - debug!("Sending config packet: {:?}", event.packet); - if let Err(e) = raw_conn.write(event.packet.clone()) { + debug!("Sending config packet: {:?}", send_config_packet.packet); + if let Err(e) = raw_conn.write(send_config_packet.packet.clone()) { error!("Failed to send packet: {e}"); } } } -/// A system that converts [`SendConfigPacketEvent`] events into triggers so -/// they get received by [`handle_outgoing_packets_observer`]. -pub fn handle_outgoing_packets( - mut commands: Commands, - mut events: EventReader<SendConfigPacketEvent>, -) { - for event in events.read() { - commands.trigger(event.clone()); - } -} /// A Bevy trigger that's sent when our client receives a [`ClientboundPing`] /// packet in the config state. /// -/// See [`PingEvent`] for more information. +/// Also see [`PingEvent`]. /// /// [`ClientboundPing`]: azalea_protocol::packets::config::ClientboundPing /// [`PingEvent`]: crate::packet::game::PingEvent #[derive(Event, Debug, Clone)] -pub struct ConfigPingEvent(pub azalea_protocol::packets::config::ClientboundPing); +pub struct ConfigPingEvent { + pub entity: Entity, + pub packet: azalea_protocol::packets::config::ClientboundPing, +} diff --git a/azalea-client/src/plugins/packet/config/mod.rs b/azalea-client/src/plugins/packet/config/mod.rs index 416019e8..e8bb017d 100644 --- a/azalea-client/src/plugins/packet/config/mod.rs +++ b/azalea-client/src/plugins/packet/config/mod.rs @@ -84,7 +84,7 @@ impl ConfigPacketHandler<'_> { pub fn disconnect(&mut self, p: &ClientboundDisconnect) { warn!("Got disconnect packet {p:?}"); - as_system::<EventWriter<_>>(self.ecs, |mut events| { + as_system::<MessageWriter<_>>(self.ecs, |mut events| { events.write(DisconnectEvent { entity: self.player, reason: Some(p.reason.clone()), @@ -126,7 +126,7 @@ impl ConfigPacketHandler<'_> { self.player ); - as_system::<(Commands, EventWriter<_>)>(self.ecs, |(mut commands, mut events)| { + as_system::<(Commands, MessageWriter<_>)>(self.ecs, |(mut commands, mut events)| { events.write(KeepAliveEvent { entity: self.player, id: p.id, @@ -142,14 +142,17 @@ impl ConfigPacketHandler<'_> { debug!("Got ping packet (in configuration) {p:?}"); as_system::<Commands>(self.ecs, |mut commands| { - commands.trigger_targets(ConfigPingEvent(p.clone()), self.player); + commands.trigger(ConfigPingEvent { + entity: self.player, + packet: p.clone(), + }); }); } pub fn resource_pack_push(&mut self, p: &ClientboundResourcePackPush) { debug!("Got resource pack push packet {p:?}"); - as_system::<EventWriter<_>>(self.ecs, |mut events| { + as_system::<MessageWriter<_>>(self.ecs, |mut events| { events.write(ResourcePackEvent { entity: self.player, id: p.id, diff --git a/azalea-client/src/plugins/packet/game/events.rs b/azalea-client/src/plugins/packet/game/events.rs index e341db3e..4ae51734 100644 --- a/azalea-client/src/plugins/packet/game/events.rs +++ b/azalea-client/src/plugins/packet/game/events.rs @@ -18,9 +18,9 @@ use crate::{client::InGameState, connection::RawConnection, player::PlayerInfo}; /// ``` /// # use azalea_client::packet::game::ReceiveGamePacketEvent; /// # use azalea_protocol::packets::game::ClientboundGamePacket; -/// # use bevy_ecs::event::EventReader; +/// # use bevy_ecs::event::MessageReader; /// -/// fn handle_packets(mut events: EventReader<ReceiveGamePacketEvent>) { +/// fn handle_packets(mut events: MessageReader<ReceiveGamePacketEvent>) { /// for ReceiveGamePacketEvent { entity, packet } in events.read() { /// match packet.as_ref() { /// ClientboundGamePacket::LevelParticles(p) => { @@ -31,7 +31,7 @@ use crate::{client::InGameState, connection::RawConnection, player::PlayerInfo}; /// } /// } /// ``` -#[derive(Event, Debug, Clone)] +#[derive(Message, Debug, Clone)] pub struct ReceiveGamePacketEvent { /// The client entity that received the packet. pub entity: Entity, @@ -40,8 +40,9 @@ pub struct ReceiveGamePacketEvent { } /// An event for sending a packet to the server while we're in the `game` state. -#[derive(Event, Clone, Debug)] +#[derive(EntityEvent, Clone, Debug)] pub struct SendPacketEvent { + #[event_target] pub sent_by: Entity, pub packet: ServerboundGamePacket, } @@ -53,7 +54,7 @@ impl SendPacketEvent { } pub fn handle_outgoing_packets_observer( - trigger: Trigger<SendPacketEvent>, + trigger: On<SendPacketEvent>, mut query: Query<(&mut RawConnection, Option<&InGameState>)>, ) { let event = trigger.event(); @@ -76,17 +77,9 @@ pub fn handle_outgoing_packets_observer( } } -/// A system that converts [`SendPacketEvent`] events into triggers so they get -/// received by [`handle_outgoing_packets_observer`]. -pub fn handle_outgoing_packets(mut commands: Commands, mut events: EventReader<SendPacketEvent>) { - for event in events.read() { - commands.trigger(event.clone()); - } -} - /// A player joined the game (or more specifically, was added to the tab /// list of a local player). -#[derive(Event, Debug, Clone)] +#[derive(Message, Debug, Clone)] pub struct AddPlayerEvent { /// The local player entity that received this event. pub entity: Entity, @@ -94,7 +87,7 @@ pub struct AddPlayerEvent { } /// A player left the game (or maybe is still in the game and was just /// removed from the tab list of a local player). -#[derive(Event, Debug, Clone)] +#[derive(Message, Debug, Clone)] pub struct RemovePlayerEvent { /// The local player entity that received this event. pub entity: Entity, @@ -102,7 +95,7 @@ pub struct RemovePlayerEvent { } /// A player was updated in the tab list of a local player (gamemode, display /// name, or latency changed). -#[derive(Event, Debug, Clone)] +#[derive(Message, Debug, Clone)] pub struct UpdatePlayerEvent { /// The local player entity that received this event. pub entity: Entity, @@ -112,7 +105,7 @@ pub struct UpdatePlayerEvent { /// Event for when an entity dies. dies. If it's a local player and there's a /// reason in the death screen, the [`ClientboundPlayerCombatKill`] will /// be included. -#[derive(Event, Debug, Clone)] +#[derive(Message, Debug, Clone)] pub struct DeathEvent { pub entity: Entity, pub packet: Option<ClientboundPlayerCombatKill>, @@ -120,7 +113,7 @@ pub struct DeathEvent { /// A KeepAlive packet is sent from the server to verify that the client is /// still connected. -#[derive(Event, Debug, Clone)] +#[derive(Message, Debug, Clone)] pub struct KeepAliveEvent { pub entity: Entity, /// The ID of the keepalive. This is an arbitrary number, but vanilla @@ -128,7 +121,7 @@ pub struct KeepAliveEvent { pub id: u64, } -#[derive(Event, Debug, Clone)] +#[derive(Message, Debug, Clone)] pub struct ResourcePackEvent { pub entity: Entity, /// The random ID for this request to download the resource pack. The packet @@ -144,7 +137,7 @@ pub struct ResourcePackEvent { /// /// Since the instance is given to you as a weak reference, it won't be able to /// be `upgrade`d if all local players leave it. -#[derive(Event, Debug, Clone)] +#[derive(Message, Debug, Clone)] pub struct InstanceLoadedEvent { pub entity: Entity, pub name: ResourceLocation, @@ -156,15 +149,10 @@ pub struct InstanceLoadedEvent { /// /// Also see [`ConfigPingEvent`] which is used for the config state. /// -/// This is not an event and can't be listened to from a normal system, -///so `EventReader<PingEvent>` will not work. -/// -/// To use it, add your "system" with `add_observer` instead of `add_systems` -/// and use `Trigger<PingEvent>` instead of `EventReader`. -/// -/// The client Entity that received the packet will be attached to the trigger. -/// /// [`ClientboundPing`]: azalea_protocol::packets::game::ClientboundPing /// [`ConfigPingEvent`]: crate::packet::config::ConfigPingEvent -#[derive(Event, Debug, Clone)] -pub struct PingEvent(pub azalea_protocol::packets::game::ClientboundPing); +#[derive(EntityEvent, Debug, Clone)] +pub struct PingEvent { + pub entity: Entity, + pub packet: azalea_protocol::packets::game::ClientboundPing, +} diff --git a/azalea-client/src/plugins/packet/game/mod.rs b/azalea-client/src/plugins/packet/game/mod.rs index fc8f34cf..dbdc8e26 100644 --- a/azalea-client/src/plugins/packet/game/mod.rs +++ b/azalea-client/src/plugins/packet/game/mod.rs @@ -207,7 +207,7 @@ impl GamePacketHandler<'_> { ), With<LocalEntity>, >, - EventWriter<InstanceLoadedEvent>, + MessageWriter<InstanceLoadedEvent>, ResMut<InstanceContainer>, ResMut<EntityUuidIndex>, Query<&mut LoadedBy, Without<LocalEntity>>, @@ -336,7 +336,7 @@ impl GamePacketHandler<'_> { // ends debug!("Got chunk batch start"); - as_system::<EventWriter<_>>(self.ecs, |mut events| { + as_system::<MessageWriter<_>>(self.ecs, |mut events| { events.write(chunks::ChunkBatchStartEvent { entity: self.player, }); @@ -346,7 +346,7 @@ impl GamePacketHandler<'_> { pub fn chunk_batch_finished(&mut self, p: &ClientboundChunkBatchFinished) { debug!("Got chunk batch finished {p:?}"); - as_system::<EventWriter<_>>(self.ecs, |mut events| { + as_system::<MessageWriter<_>>(self.ecs, |mut events| { events.write(chunks::ChunkBatchFinishedEvent { entity: self.player, batch_size: p.batch_size, @@ -387,7 +387,7 @@ impl GamePacketHandler<'_> { pub fn disconnect(&mut self, p: &ClientboundDisconnect) { warn!("Got disconnect packet {p:?}"); - as_system::<EventWriter<_>>(self.ecs, |mut events| { + as_system::<MessageWriter<_>>(self.ecs, |mut events| { events.write(DisconnectEvent { entity: self.player, reason: Some(p.reason.clone()), @@ -440,8 +440,8 @@ impl GamePacketHandler<'_> { as_system::<( Query<&mut TabList>, - EventWriter<AddPlayerEvent>, - EventWriter<UpdatePlayerEvent>, + MessageWriter<AddPlayerEvent>, + MessageWriter<UpdatePlayerEvent>, ResMut<TabList>, )>( self.ecs, @@ -500,7 +500,7 @@ impl GamePacketHandler<'_> { as_system::<( Query<&mut TabList>, - EventWriter<RemovePlayerEvent>, + MessageWriter<RemovePlayerEvent>, ResMut<TabList>, )>( self.ecs, @@ -542,7 +542,7 @@ impl GamePacketHandler<'_> { pub fn level_chunk_with_light(&mut self, p: &ClientboundLevelChunkWithLight) { debug!("Got chunk with light packet {} {}", p.x, p.z); - as_system::<EventWriter<_>>(self.ecs, |mut events| { + as_system::<MessageWriter<_>>(self.ecs, |mut events| { events.write(chunks::ReceiveChunkEvent { entity: self.player, packet: p.clone(), @@ -740,7 +740,7 @@ impl GamePacketHandler<'_> { instance_holder.partial_instance.clone(), move |entity_mut| { entity_mut.world_scope(|world| { - world.send_event(KnockbackEvent { entity, knockback }) + world.write_message(KnockbackEvent { entity, knockback }) }); }, )); @@ -957,7 +957,7 @@ impl GamePacketHandler<'_> { pub fn keep_alive(&mut self, p: &ClientboundKeepAlive) { debug!("Got keep alive packet {p:?} for {:?}", self.player); - as_system::<(EventWriter<KeepAliveEvent>, Commands)>( + as_system::<(MessageWriter<KeepAliveEvent>, Commands)>( self.ecs, |(mut keepalive_events, mut commands)| { keepalive_events.write(KeepAliveEvent { @@ -1011,7 +1011,7 @@ impl GamePacketHandler<'_> { pub fn player_chat(&mut self, p: &ClientboundPlayerChat) { debug!("Got player chat packet {p:?}"); - as_system::<EventWriter<_>>(self.ecs, |mut events| { + as_system::<MessageWriter<_>>(self.ecs, |mut events| { events.write(ChatReceivedEvent { entity: self.player, packet: ChatPacket::Player(Arc::new(p.clone())), @@ -1022,7 +1022,7 @@ impl GamePacketHandler<'_> { pub fn system_chat(&mut self, p: &ClientboundSystemChat) { debug!("Got system chat packet {p:?}"); - as_system::<EventWriter<_>>(self.ecs, |mut events| { + as_system::<MessageWriter<_>>(self.ecs, |mut events| { events.write(ChatReceivedEvent { entity: self.player, packet: ChatPacket::System(Arc::new(p.clone())), @@ -1033,7 +1033,7 @@ impl GamePacketHandler<'_> { pub fn disguised_chat(&mut self, p: &ClientboundDisguisedChat) { debug!("Got disguised chat packet {p:?}"); - as_system::<EventWriter<_>>(self.ecs, |mut events| { + as_system::<MessageWriter<_>>(self.ecs, |mut events| { events.write(ChatReceivedEvent { entity: self.player, packet: ChatPacket::Disguised(Arc::new(p.clone())), @@ -1227,7 +1227,7 @@ impl GamePacketHandler<'_> { pub fn explode(&mut self, p: &ClientboundExplode) { trace!("Got explode packet {p:?}"); - as_system::<EventWriter<_>>(self.ecs, |mut knockback_events| { + as_system::<MessageWriter<_>>(self.ecs, |mut knockback_events| { if let Some(knockback) = p.knockback { knockback_events.write(KnockbackEvent { entity: self.player, @@ -1278,7 +1278,10 @@ impl GamePacketHandler<'_> { debug!("Got ping packet {p:?}"); as_system::<Commands>(self.ecs, |mut commands| { - commands.trigger_targets(PingEvent(p.clone()), self.player); + commands.trigger(PingEvent { + entity: self.player, + packet: p.clone(), + }); }); } @@ -1294,7 +1297,7 @@ impl GamePacketHandler<'_> { as_system::<( Commands, Query<(&MinecraftEntityId, Option<&Dead>)>, - EventWriter<_>, + MessageWriter<_>, )>(self.ecs, |(mut commands, mut query, mut events)| { let (entity_id, dead) = query.get_mut(self.player).unwrap(); @@ -1315,7 +1318,7 @@ impl GamePacketHandler<'_> { pub fn resource_pack_push(&mut self, p: &ClientboundResourcePackPush) { debug!("Got resource pack packet {p:?}"); - as_system::<EventWriter<_>>(self.ecs, |mut events| { + as_system::<MessageWriter<_>>(self.ecs, |mut events| { events.write(ResourcePackEvent { entity: self.player, id: p.id, @@ -1343,7 +1346,7 @@ impl GamePacketHandler<'_> { ), With<LocalEntity>, >, - EventWriter<_>, + MessageWriter<_>, ResMut<InstanceContainer>, Query<&mut LoadedBy, Without<LocalEntity>>, )>( diff --git a/azalea-client/src/plugins/packet/login/events.rs b/azalea-client/src/plugins/packet/login/events.rs index fc7a6b22..f50c1423 100644 --- a/azalea-client/src/plugins/packet/login/events.rs +++ b/azalea-client/src/plugins/packet/login/events.rs @@ -12,7 +12,7 @@ use tracing::{debug, error}; use super::InLoginState; use crate::{Account, connection::RawConnection}; -#[derive(Event, Debug, Clone)] +#[derive(Message, Debug, Clone)] pub struct ReceiveLoginPacketEvent { /// The client entity that received the packet. pub entity: Entity, @@ -20,13 +20,14 @@ pub struct ReceiveLoginPacketEvent { pub packet: Arc<ClientboundLoginPacket>, } -#[derive(Event, Debug, Clone)] +#[derive(EntityEvent, Debug, Clone)] pub struct ReceiveHelloEvent { + pub entity: Entity, pub account: Account, pub packet: ClientboundHello, } -#[derive(Event, Debug, Clone)] +#[derive(Message, Debug, Clone)] pub struct ReceiveCustomQueryEvent { /// The client entity that received the packet. pub entity: Entity, @@ -40,8 +41,9 @@ pub struct ReceiveCustomQueryEvent { } /// Event for sending a login packet to the server. -#[derive(Event, Debug, Clone)] +#[derive(EntityEvent, Debug, Clone)] pub struct SendLoginPacketEvent { + #[event_target] pub sent_by: Entity, pub packet: ServerboundLoginPacket, } @@ -56,7 +58,7 @@ impl SendLoginPacketEvent { } pub fn handle_outgoing_packets_observer( - trigger: Trigger<SendLoginPacketEvent>, + trigger: On<SendLoginPacketEvent>, mut query: Query<(&mut RawConnection, Option<&InLoginState>)>, ) { let event = trigger.event(); @@ -74,13 +76,3 @@ pub fn handle_outgoing_packets_observer( } } } -/// A system that converts [`SendLoginPacketEvent`] events into triggers so -/// they get received by [`handle_outgoing_packets_observer`]. -pub fn handle_outgoing_packets( - mut commands: Commands, - mut events: EventReader<SendLoginPacketEvent>, -) { - for event in events.read() { - commands.trigger(event.clone()); - } -} diff --git a/azalea-client/src/plugins/packet/login/mod.rs b/azalea-client/src/plugins/packet/login/mod.rs index 03e87920..63226124 100644 --- a/azalea-client/src/plugins/packet/login/mod.rs +++ b/azalea-client/src/plugins/packet/login/mod.rs @@ -59,19 +59,17 @@ impl LoginPacketHandler<'_> { ); return; }; - commands.trigger_targets( - ReceiveHelloEvent { - account: account.clone(), - packet: p.clone(), - }, - self.player, - ); + commands.trigger(ReceiveHelloEvent { + entity: self.player, + account: account.clone(), + packet: p.clone(), + }); }); } pub fn login_disconnect(&mut self, p: &ClientboundLoginDisconnect) { debug!("Got disconnect {:?}", p); - as_system::<EventWriter<_>>(self.ecs, |mut events| { + as_system::<MessageWriter<_>>(self.ecs, |mut events| { events.write(DisconnectEvent { entity: self.player, reason: Some(p.reason.clone()), @@ -120,7 +118,7 @@ impl LoginPacketHandler<'_> { pub fn custom_query(&mut self, p: &ClientboundCustomQuery) { debug!("Got custom query {p:?}"); - as_system::<EventWriter<ReceiveCustomQueryEvent>>(self.ecs, |mut events| { + as_system::<MessageWriter<ReceiveCustomQueryEvent>>(self.ecs, |mut events| { events.write(ReceiveCustomQueryEvent { entity: self.player, packet: p.clone(), diff --git a/azalea-client/src/plugins/packet/mod.rs b/azalea-client/src/plugins/packet/mod.rs index 2602e878..30503d50 100644 --- a/azalea-client/src/plugins/packet/mod.rs +++ b/azalea-client/src/plugins/packet/mod.rs @@ -16,7 +16,7 @@ pub struct PacketPlugin; pub fn death_event_on_0_health( query: Query<(Entity, &Health), Changed<Health>>, - mut death_events: EventWriter<DeathEvent>, + mut death_events: MessageWriter<DeathEvent>, ) { for (entity, health) in query.iter() { if **health == 0. { @@ -33,35 +33,20 @@ impl Plugin for PacketPlugin { app.add_observer(game::handle_outgoing_packets_observer) .add_observer(config::handle_outgoing_packets_observer) .add_observer(login::handle_outgoing_packets_observer) - .add_systems( - Update, - ( - ( - config::handle_outgoing_packets, - game::handle_outgoing_packets, - login::handle_outgoing_packets, - ) - .chain(), - death_event_on_0_health.before(death_listener), - ), - ) - .add_event::<game::ReceiveGamePacketEvent>() - .add_event::<config::ReceiveConfigPacketEvent>() - .add_event::<login::ReceiveLoginPacketEvent>() + .add_systems(Update, death_event_on_0_health.before(death_listener)) + .add_message::<game::ReceiveGamePacketEvent>() + .add_message::<config::ReceiveConfigPacketEvent>() + .add_message::<login::ReceiveLoginPacketEvent>() // - .add_event::<game::SendPacketEvent>() - .add_event::<config::SendConfigPacketEvent>() - .add_event::<login::SendLoginPacketEvent>() - // - .add_event::<game::AddPlayerEvent>() - .add_event::<game::RemovePlayerEvent>() - .add_event::<game::UpdatePlayerEvent>() - .add_event::<ChatReceivedEvent>() - .add_event::<game::DeathEvent>() - .add_event::<game::KeepAliveEvent>() - .add_event::<game::ResourcePackEvent>() - .add_event::<game::InstanceLoadedEvent>() - .add_event::<login::ReceiveCustomQueryEvent>(); + .add_message::<game::AddPlayerEvent>() + .add_message::<game::RemovePlayerEvent>() + .add_message::<game::UpdatePlayerEvent>() + .add_message::<ChatReceivedEvent>() + .add_message::<game::DeathEvent>() + .add_message::<game::KeepAliveEvent>() + .add_message::<game::ResourcePackEvent>() + .add_message::<game::InstanceLoadedEvent>() + .add_message::<login::ReceiveCustomQueryEvent>(); } } diff --git a/azalea-client/src/plugins/pong.rs b/azalea-client/src/plugins/pong.rs index e23b5245..f268a836 100644 --- a/azalea-client/src/plugins/pong.rs +++ b/azalea-client/src/plugins/pong.rs @@ -1,3 +1,4 @@ +use azalea_protocol::packets::{config, game}; use bevy_app::{App, Plugin}; use bevy_ecs::prelude::*; @@ -22,16 +23,16 @@ impl Plugin for PongPlugin { } } -pub fn reply_to_game_ping(trigger: Trigger<PingEvent>, mut commands: Commands) { +pub fn reply_to_game_ping(ping: On<PingEvent>, mut commands: Commands) { commands.trigger(SendPacketEvent::new( - trigger.target(), - azalea_protocol::packets::game::ServerboundPong { id: trigger.0.id }, + ping.entity, + game::ServerboundPong { id: ping.packet.id }, )); } -pub fn reply_to_config_ping(trigger: Trigger<ConfigPingEvent>, mut commands: Commands) { +pub fn reply_to_config_ping(ping: On<ConfigPingEvent>, mut commands: Commands) { commands.trigger(SendConfigPacketEvent::new( - trigger.target(), - azalea_protocol::packets::config::ServerboundPong { id: trigger.0.id }, + ping.entity, + config::ServerboundPong { id: ping.packet.id }, )); } diff --git a/azalea-client/src/plugins/respawn.rs b/azalea-client/src/plugins/respawn.rs index f0ddd2b8..ecc773c4 100644 --- a/azalea-client/src/plugins/respawn.rs +++ b/azalea-client/src/plugins/respawn.rs @@ -5,7 +5,7 @@ use bevy_ecs::prelude::*; use crate::packet::game::SendPacketEvent; /// Tell the server that we're respawning. -#[derive(Event, Debug, Clone)] +#[derive(Message, Debug, Clone)] pub struct PerformRespawnEvent { pub entity: Entity, } @@ -14,12 +14,12 @@ pub struct PerformRespawnEvent { pub struct RespawnPlugin; impl Plugin for RespawnPlugin { fn build(&self, app: &mut App) { - app.add_event::<PerformRespawnEvent>() + app.add_message::<PerformRespawnEvent>() .add_systems(Update, perform_respawn); } } -pub fn perform_respawn(mut events: EventReader<PerformRespawnEvent>, mut commands: Commands) { +pub fn perform_respawn(mut events: MessageReader<PerformRespawnEvent>, mut commands: Commands) { for event in events.read() { commands.trigger(SendPacketEvent::new( event.entity, |
