mirror of
https://github.com/mat-1/azalea.git
synced 2025-08-02 14:26:04 +00:00
PongPlugin
This commit is contained in:
parent
4c53498f07
commit
8af265e48b
9 changed files with 113 additions and 17 deletions
|
@ -84,6 +84,7 @@ use crate::{
|
|||
login::{self, InLoginState, LoginSendPacketQueue},
|
||||
},
|
||||
player::retroactively_add_game_profile_component,
|
||||
pong::PongPlugin,
|
||||
raw_connection::RawConnection,
|
||||
respawn::RespawnPlugin,
|
||||
task_pool::TaskPoolPlugin,
|
||||
|
@ -1035,7 +1036,8 @@ impl PluginGroup for DefaultPlugins {
|
|||
.add(ChunksPlugin)
|
||||
.add(TickEndPlugin)
|
||||
.add(BrandPlugin)
|
||||
.add(TickBroadcastPlugin);
|
||||
.add(TickBroadcastPlugin)
|
||||
.add(PongPlugin);
|
||||
#[cfg(feature = "log")]
|
||||
{
|
||||
group = group.add(bevy_log::LogPlugin::default());
|
||||
|
|
|
@ -191,12 +191,11 @@ pub fn spawn_listener(
|
|||
|
||||
pub fn chat_listener(query: Query<&LocalPlayerEvents>, mut events: EventReader<ChatReceivedEvent>) {
|
||||
for event in events.read() {
|
||||
let local_player_events = query
|
||||
.get(event.entity)
|
||||
.expect("Non-local entities shouldn't be able to receive chat events");
|
||||
if let Ok(local_player_events) = query.get(event.entity) {
|
||||
let _ = local_player_events.send(Event::Chat(event.packet.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// only tick if we're in a world
|
||||
pub fn tick_listener(query: Query<&LocalPlayerEvents, With<InstanceName>>) {
|
||||
|
@ -210,12 +209,11 @@ pub fn packet_listener(
|
|||
mut events: EventReader<ReceivePacketEvent>,
|
||||
) {
|
||||
for event in events.read() {
|
||||
let local_player_events = query
|
||||
.get(event.entity)
|
||||
.expect("Non-local entities shouldn't be able to receive packet events");
|
||||
if let Ok(local_player_events) = query.get(event.entity) {
|
||||
let _ = local_player_events.send(Event::Packet(event.packet.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_player_listener(
|
||||
query: Query<&LocalPlayerEvents>,
|
||||
|
|
|
@ -9,6 +9,7 @@ pub mod inventory;
|
|||
pub mod mining;
|
||||
pub mod movement;
|
||||
pub mod packet;
|
||||
pub mod pong;
|
||||
pub mod respawn;
|
||||
pub mod task_pool;
|
||||
pub mod tick_end;
|
||||
|
|
|
@ -109,3 +109,13 @@ fn packet_interrupts(packet: &ClientboundConfigPacket) -> bool {
|
|||
| ClientboundConfigPacket::Transfer(_)
|
||||
)
|
||||
}
|
||||
|
||||
/// A Bevy trigger that's sent when our client receives a [`ClientboundPing`]
|
||||
/// packet in the config state.
|
||||
///
|
||||
/// See [`PingEvent`] for more information.
|
||||
///
|
||||
/// [`ClientboundPing`]: azalea_protocol::packets::config::ClientboundPing
|
||||
/// [`PingEvent`]: crate::packet::game::PingEvent
|
||||
#[derive(Event, Debug, Clone)]
|
||||
pub struct ConfigPingEvent(pub azalea_protocol::packets::config::ClientboundPing);
|
||||
|
|
|
@ -142,10 +142,8 @@ impl ConfigPacketHandler<'_> {
|
|||
pub fn ping(&mut self, p: ClientboundPing) {
|
||||
debug!("Got ping packet (in configuration) {p:?}");
|
||||
|
||||
as_system::<Query<&RawConnection>>(self.ecs, |query| {
|
||||
let raw_conn = query.get(self.player).unwrap();
|
||||
|
||||
raw_conn.write_packet(ServerboundPong { id: p.id }).unwrap();
|
||||
as_system::<Commands>(self.ecs, |mut commands| {
|
||||
commands.trigger_targets(ConfigPingEvent(p), self.player);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -212,3 +212,21 @@ pub struct InstanceLoadedEvent {
|
|||
pub name: ResourceLocation,
|
||||
pub instance: Weak<RwLock<Instance>>,
|
||||
}
|
||||
|
||||
/// A Bevy trigger that's sent when our client receives a [`ClientboundPing`]
|
||||
/// packet in the game state.
|
||||
///
|
||||
/// 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);
|
||||
|
|
|
@ -1363,10 +1363,7 @@ impl GamePacketHandler<'_> {
|
|||
debug!("Got ping packet {p:?}");
|
||||
|
||||
as_system::<Commands>(self.ecs, |mut commands| {
|
||||
commands.trigger(SendPacketEvent::new(
|
||||
self.player,
|
||||
ServerboundPong { id: p.id },
|
||||
));
|
||||
commands.trigger_targets(PingEvent(p.clone()), self.player);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
37
azalea-client/src/plugins/pong.rs
Normal file
37
azalea-client/src/plugins/pong.rs
Normal file
|
@ -0,0 +1,37 @@
|
|||
use bevy_app::{App, Plugin};
|
||||
use bevy_ecs::prelude::*;
|
||||
|
||||
use super::packet::{
|
||||
config::{ConfigPingEvent, SendConfigPacketEvent},
|
||||
game::PingEvent,
|
||||
};
|
||||
use crate::packet::game::SendPacketEvent;
|
||||
|
||||
/// A plugin that replies to [`ClientboundPing`] packets with
|
||||
/// [`ServerboundPong`].
|
||||
///
|
||||
/// This works in both the `game` and `config` states.
|
||||
///
|
||||
/// [`ClientboundPing`]: azalea_protocol::packets::game::ClientboundPing
|
||||
/// [`ServerboundPong`]: azalea_protocol::packets::game::ServerboundPong
|
||||
pub struct PongPlugin;
|
||||
impl Plugin for PongPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.add_observer(reply_to_game_ping)
|
||||
.add_observer(reply_to_config_ping);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reply_to_game_ping(trigger: Trigger<PingEvent>, mut commands: Commands) {
|
||||
commands.trigger(SendPacketEvent::new(
|
||||
trigger.entity(),
|
||||
azalea_protocol::packets::game::ServerboundPong { id: trigger.0.id },
|
||||
));
|
||||
}
|
||||
|
||||
pub fn reply_to_config_ping(trigger: Trigger<ConfigPingEvent>, mut commands: Commands) {
|
||||
commands.trigger(SendConfigPacketEvent::new(
|
||||
trigger.entity(),
|
||||
azalea_protocol::packets::config::ServerboundPong { id: trigger.0.id },
|
||||
));
|
||||
}
|
35
azalea-client/tests/reply_to_ping_with_pong.rs
Normal file
35
azalea-client/tests/reply_to_ping_with_pong.rs
Normal file
|
@ -0,0 +1,35 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use azalea_client::{packet::game::SendPacketEvent, test_simulation::*};
|
||||
use azalea_protocol::packets::{
|
||||
ConnectionProtocol,
|
||||
game::{ClientboundPing, ServerboundGamePacket},
|
||||
};
|
||||
use bevy_ecs::observer::Trigger;
|
||||
use bevy_log::tracing_subscriber;
|
||||
use parking_lot::Mutex;
|
||||
|
||||
#[test]
|
||||
fn reply_to_ping_with_pong() {
|
||||
let _ = tracing_subscriber::fmt::try_init();
|
||||
|
||||
let mut simulation = Simulation::new(ConnectionProtocol::Game);
|
||||
let reply_count = Arc::new(Mutex::new(0));
|
||||
let reply_count_clone = reply_count.clone();
|
||||
simulation
|
||||
.app
|
||||
.add_observer(move |trigger: Trigger<SendPacketEvent>| {
|
||||
if trigger.sent_by == simulation.entity {
|
||||
if let ServerboundGamePacket::Pong(packet) = &trigger.packet {
|
||||
assert_eq!(packet.id, 123);
|
||||
*reply_count_clone.lock() += 1;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
simulation.tick();
|
||||
simulation.receive_packet(ClientboundPing { id: 123 });
|
||||
simulation.tick();
|
||||
|
||||
assert_eq!(*reply_count.lock(), 1);
|
||||
}
|
Loading…
Add table
Reference in a new issue