1
2
Fork 0
mirror of https://github.com/mat-1/azalea.git synced 2025-08-02 06:16:04 +00:00

use systemstate for packet handler

This commit is contained in:
Ubuntu 2023-01-13 22:05:51 +00:00
parent 9f634a4d83
commit c74ffc03ec
3 changed files with 154 additions and 62 deletions

View file

@ -163,8 +163,8 @@ impl Client {
/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let account = Account::offline("bot");
/// let (client, rx) = Client::join(&account, "localhost").await?;
/// client.chat("Hello, world!").await?;
/// client.disconnect().await?;
/// client.chat("Hello, world!");
/// client.disconnect();
/// Ok(())
/// }
/// ```
@ -483,7 +483,6 @@ impl Client {
}
}
/// Start the protocol and game tick loop.
#[doc(hidden)]
pub fn start_ecs(
run_schedule_receiver: mpsc::UnboundedReceiver<()>,

View file

@ -25,7 +25,7 @@ use bevy_ecs::{
prelude::Entity,
query::Changed,
schedule::{IntoSystemDescriptor, SystemSet},
system::{Commands, Query, ResMut},
system::{Commands, Query, Res, ResMut, SystemState},
};
use log::{debug, error, trace, warn};
use parking_lot::Mutex;
@ -41,10 +41,23 @@ impl Plugin for PacketHandlerPlugin {
SystemSet::new()
.with_system(handle_packets.label("packet"))
.with_system(clear_packets.after("packet")),
);
)
.add_event::<AddPlayerEvent>()
.add_event::<RemovePlayerEvent>()
.add_event::<UpdatePlayerEvent>();
}
}
/// A player joined the game (or more specifically, was added to the tab
/// list).
pub struct AddPlayerEvent(PlayerInfo);
/// A player left the game (or maybe is still in the game and was just
/// removed from the tab list).
pub struct RemovePlayerEvent(PlayerInfo);
/// A player was updated in the tab list (gamemode, display
/// name, or latency changed).
pub struct UpdatePlayerEvent(PlayerInfo);
/// Something that receives packets from the server.
#[derive(Component, Clone)]
pub struct PacketReceiver {
@ -52,35 +65,37 @@ pub struct PacketReceiver {
pub run_schedule_sender: mpsc::UnboundedSender<()>,
}
fn handle_packets(
mut commands: Commands,
fn handle_packets(ecs: &mut bevy_ecs::world::World) {
let mut events_owned = Vec::new();
query: Query<(Entity, &PacketReceiver), Changed<PacketReceiver>>,
local_player_query: Query<&LocalPlayer>,
entity_kind_query: Query<&EntityKind>,
mut mut_local_player_query: Query<&mut LocalPlayer>,
mut mut_health_query: Query<&mut Health>,
mut mut_position_query: Query<&mut Position>,
combat_kill_query: Query<(&MinecraftEntityId, Option<&Dead>)>,
mut position_query: Query<(
&mut LocalPlayer,
&mut Physics,
&mut Position,
&mut LastSentPosition,
)>,
mut world_container: ResMut<WorldContainer>,
mut entity_infos: ResMut<EntityInfos>,
) {
for (player_entity, packet_events) in &query {
let packets = packet_events.packets.lock();
{
let mut system_state: SystemState<
Query<(Entity, &PacketReceiver), Changed<PacketReceiver>>,
> = SystemState::new(ecs);
let query = system_state.get(ecs);
for (player_entity, packet_events) in &query {
let packets = packet_events.packets.lock();
if !packets.is_empty() {
events_owned.push((player_entity, packets.clone()));
}
}
}
for (player_entity, packets) in events_owned {
for packet in packets.iter() {
match packet {
ClientboundGamePacket::Login(p) => {
debug!("Got login packet");
let mut local_player = mut_local_player_query.get_mut(player_entity).unwrap();
let mut system_state: SystemState<(
Commands,
Query<&mut LocalPlayer>,
ResMut<WorldContainer>,
ResMut<EntityInfos>,
)> = SystemState::new(ecs);
let (mut commands, mut query, mut world_container, mut entity_infos) =
system_state.get_mut(ecs);
let mut local_player = query.get_mut(player_entity).unwrap();
{
// TODO: have registry_holder be a struct because this sucks rn
@ -191,6 +206,8 @@ fn handle_packets(
);
local_player.tx.send(Event::Login).unwrap();
system_state.apply(ecs);
}
ClientboundGamePacket::SetChunkCacheRadius(p) => {
debug!("Got set chunk cache radius packet {:?}", p);
@ -215,7 +232,9 @@ fn handle_packets(
}
ClientboundGamePacket::Disconnect(p) => {
debug!("Got disconnect packet {:?}", p);
let local_player = local_player_query.get(player_entity).unwrap();
let mut system_state: SystemState<Query<&LocalPlayer>> = SystemState::new(ecs);
let query = system_state.get(ecs);
let local_player = query.get(player_entity).unwrap();
local_player.disconnect();
}
ClientboundGamePacket::UpdateRecipes(_p) => {
@ -231,8 +250,17 @@ fn handle_packets(
// TODO: reply with teleport confirm
debug!("Got player position packet {:?}", p);
let mut system_state: SystemState<
Query<(
&mut LocalPlayer,
&mut Physics,
&mut Position,
&mut LastSentPosition,
)>,
> = SystemState::new(ecs);
let mut query = system_state.get_mut(ecs);
let (mut local_player, mut physics, mut position, mut last_sent_position) =
position_query.get_mut(player_entity).unwrap();
query.get_mut(player_entity).unwrap();
let delta_movement = physics.delta;
@ -308,7 +336,10 @@ fn handle_packets(
ClientboundGamePacket::PlayerInfoUpdate(p) => {
debug!("Got player info packet {:?}", p);
let mut local_player = mut_local_player_query.get_mut(player_entity).unwrap();
let mut system_state: SystemState<Query<&mut LocalPlayer>> =
SystemState::new(ecs);
let mut query = system_state.get_mut(ecs);
let mut local_player = query.get_mut(player_entity).unwrap();
for updated_info in &p.entries {
// add the new player maybe
@ -349,7 +380,10 @@ fn handle_packets(
}
}
ClientboundGamePacket::PlayerInfoRemove(p) => {
let mut local_player = mut_local_player_query.get_mut(player_entity).unwrap();
let mut system_state: SystemState<Query<&mut LocalPlayer>> =
SystemState::new(ecs);
let mut query = system_state.get_mut(ecs);
let mut local_player = query.get_mut(player_entity).unwrap();
for uuid in &p.profile_ids {
if let Some(info) = local_player.players.remove(uuid) {
@ -360,7 +394,10 @@ fn handle_packets(
ClientboundGamePacket::SetChunkCacheCenter(p) => {
debug!("Got chunk cache center packet {:?}", p);
let local_player = local_player_query.get(player_entity).unwrap();
let mut system_state: SystemState<Query<&mut LocalPlayer>> =
SystemState::new(ecs);
let mut query = system_state.get_mut(ecs);
let mut local_player = query.get_mut(player_entity).unwrap();
let mut partial_world = local_player.partial_world.write();
partial_world.chunks.view_center = ChunkPos::new(p.x, p.z);
@ -369,7 +406,11 @@ fn handle_packets(
// debug!("Got chunk with light packet {} {}", p.x, p.z);
let pos = ChunkPos::new(p.x, p.z);
let local_player = local_player_query.get(player_entity).unwrap();
let mut system_state: SystemState<Query<&mut LocalPlayer>> =
SystemState::new(ecs);
let mut query = system_state.get_mut(ecs);
let mut local_player = query.get_mut(player_entity).unwrap();
let world = local_player.world.read();
let partial_world = local_player.partial_world.read();
@ -407,7 +448,11 @@ fn handle_packets(
ClientboundGamePacket::AddEntity(p) => {
debug!("Got add entity packet {:?}", p);
let local_player = local_player_query.get(player_entity).unwrap();
let mut system_state: SystemState<(Commands, Query<&mut LocalPlayer>)> =
SystemState::new(ecs);
let (mut commands, mut query) = system_state.get_mut(ecs);
let mut local_player = query.get_mut(player_entity).unwrap();
if let Some(world_name) = &local_player.world_name {
let bundle = p.as_entity_bundle(world_name.clone());
let mut entity_commands = commands.spawn((MinecraftEntityId(p.id), bundle));
@ -421,7 +466,13 @@ fn handle_packets(
ClientboundGamePacket::SetEntityData(p) => {
debug!("Got set entity data packet {:?}", p);
let local_player = local_player_query.get(player_entity).unwrap();
let mut system_state: SystemState<(
Commands,
Query<(&mut LocalPlayer, &EntityKind)>,
)> = SystemState::new(ecs);
let (mut commands, mut query) = system_state.get_mut(ecs);
let (mut local_player, entity_kind) = query.get_mut(player_entity).unwrap();
let partial_world = local_player.partial_world.write();
let entity = partial_world
.entity_infos
@ -429,9 +480,6 @@ fn handle_packets(
drop(partial_world);
if let Some(entity) = entity {
let entity_kind = entity_kind_query
.get(entity)
.expect("EntityKind should always be present");
let mut entity_commands = commands.entity(entity);
if let Err(e) = apply_metadata(
&mut entity_commands,
@ -456,7 +504,13 @@ fn handle_packets(
ClientboundGamePacket::AddPlayer(p) => {
debug!("Got add player packet {:?}", p);
let local_player = local_player_query.get(player_entity).unwrap();
let mut system_state: SystemState<(
Commands,
Query<(&mut LocalPlayer, &EntityKind)>,
)> = SystemState::new(ecs);
let (mut commands, mut query) = system_state.get_mut(ecs);
let (mut local_player, entity_kind) = query.get_mut(player_entity).unwrap();
if let Some(world_name) = &local_player.world_name {
let bundle = p.as_player_bundle(world_name.clone());
commands.spawn((MinecraftEntityId(p.id), bundle));
@ -479,25 +533,31 @@ fn handle_packets(
ClientboundGamePacket::SetHealth(p) => {
debug!("Got set health packet {:?}", p);
let mut health = mut_health_query.get_mut(player_entity).unwrap();
let mut system_state: SystemState<Query<&mut Health>> = SystemState::new(ecs);
let mut query = system_state.get_mut(ecs);
let mut health = query.get_mut(player_entity).unwrap();
**health = p.health;
// the `Dead` component is added by `update_dead` in
// azalea-world and then the
// `dead_event` system fires the Death event.
// the `Dead` component is added by the `update_dead` system
// in azalea-world and then the `dead_event` system fires
// the Death event.
}
ClientboundGamePacket::SetExperience(p) => {
debug!("Got set experience packet {:?}", p);
}
ClientboundGamePacket::TeleportEntity(p) => {
let local_player = local_player_query.get(player_entity).unwrap();
let mut system_state: SystemState<Query<(&mut LocalPlayer, &mut Position)>> =
SystemState::new(ecs);
let mut query = system_state.get_mut(ecs);
let (mut local_player, mut position) = query.get_mut(player_entity).unwrap();
let partial_world = local_player.partial_world.read();
let partial_entity_infos = &partial_world.entity_infos;
let entity = partial_entity_infos.get_by_id(MinecraftEntityId(p.id));
drop(partial_world);
if let Some(entity) = entity {
let mut position = mut_position_query.get_mut(entity).unwrap();
**position = p.position;
} else {
warn!("Got teleport entity packet for unknown entity id {}", p.id);
@ -510,14 +570,17 @@ fn handle_packets(
// debug!("Got rotate head packet {:?}", p);
}
ClientboundGamePacket::MoveEntityPos(p) => {
let local_player = local_player_query.get(player_entity).unwrap();
let mut system_state: SystemState<Query<(&mut LocalPlayer, &mut Position)>> =
SystemState::new(ecs);
let mut query = system_state.get_mut(ecs);
let (mut local_player, mut position) = query.get_mut(player_entity).unwrap();
let partial_world = local_player.partial_world.read();
let partial_entity_infos = &partial_world.entity_infos;
let entity = partial_entity_infos.get_by_id(MinecraftEntityId(p.entity_id));
drop(partial_world);
if let Some(entity) = entity {
let mut position = mut_position_query.get_mut(entity).unwrap();
**position = position.with_delta(&p.delta);
} else {
warn!(
@ -527,14 +590,17 @@ fn handle_packets(
}
}
ClientboundGamePacket::MoveEntityPosRot(p) => {
let local_player = local_player_query.get(player_entity).unwrap();
let mut system_state: SystemState<Query<(&mut LocalPlayer, &mut Position)>> =
SystemState::new(ecs);
let mut query = system_state.get_mut(ecs);
let (mut local_player, mut position) = query.get_mut(player_entity).unwrap();
let partial_world = local_player.partial_world.read();
let partial_entity_infos = &partial_world.entity_infos;
let entity = partial_entity_infos.get_by_id(MinecraftEntityId(p.entity_id));
drop(partial_world);
if let Some(entity) = entity {
let mut position = mut_position_query.get_mut(entity).unwrap();
**position = position.with_delta(&p.delta);
} else {
warn!(
@ -549,7 +615,12 @@ fn handle_packets(
ClientboundGamePacket::KeepAlive(p) => {
debug!("Got keep alive packet {:?}", p);
let mut local_player = mut_local_player_query.get_mut(player_entity).unwrap();
let mut system_state: SystemState<Query<&mut LocalPlayer>> =
SystemState::new(ecs);
let mut query = system_state.get_mut(ecs);
let mut local_player = query.get_mut(player_entity).unwrap();
let mut local_player = query.get_mut(player_entity).unwrap();
local_player.write_packet(ServerboundKeepAlivePacket { id: p.id }.get());
}
ClientboundGamePacket::RemoveEntities(p) => {
@ -558,7 +629,10 @@ fn handle_packets(
ClientboundGamePacket::PlayerChat(p) => {
debug!("Got player chat packet {:?}", p);
let local_player = local_player_query.get(player_entity).unwrap();
let mut system_state: SystemState<Query<&mut LocalPlayer>> =
SystemState::new(ecs);
let mut query = system_state.get_mut(ecs);
let local_player = query.get_mut(player_entity).unwrap();
local_player
.tx
@ -568,7 +642,10 @@ fn handle_packets(
ClientboundGamePacket::SystemChat(p) => {
debug!("Got system chat packet {:?}", p);
let local_player = local_player_query.get(player_entity).unwrap();
let mut system_state: SystemState<Query<&mut LocalPlayer>> =
SystemState::new(ecs);
let mut query = system_state.get_mut(ecs);
let local_player = query.get_mut(player_entity).unwrap();
local_player
.tx
@ -584,7 +661,11 @@ fn handle_packets(
ClientboundGamePacket::BlockUpdate(p) => {
debug!("Got block update packet {:?}", p);
let local_player = local_player_query.get(player_entity).unwrap();
let mut system_state: SystemState<Query<&mut LocalPlayer>> =
SystemState::new(ecs);
let mut query = system_state.get_mut(ecs);
let local_player = query.get_mut(player_entity).unwrap();
let world = local_player.world.write();
world.chunks.set_block_state(&p.pos, p.block_state);
@ -594,7 +675,11 @@ fn handle_packets(
}
ClientboundGamePacket::SectionBlocksUpdate(p) => {
debug!("Got section blocks update packet {:?}", p);
let local_player = local_player_query.get(player_entity).unwrap();
let mut system_state: SystemState<Query<&mut LocalPlayer>> =
SystemState::new(ecs);
let mut query = system_state.get_mut(ecs);
let local_player = query.get_mut(player_entity).unwrap();
let world = local_player.world.write();
for state in &p.states {
@ -646,12 +731,17 @@ fn handle_packets(
ClientboundGamePacket::PlayerCombatEnter(_) => {}
ClientboundGamePacket::PlayerCombatKill(p) => {
debug!("Got player kill packet {:?}", p);
let (&entity_id, dead) = combat_kill_query.get(player_entity).unwrap();
if *entity_id == p.player_id && dead.is_none() {
let mut system_state: SystemState<(
Commands,
Query<(&mut LocalPlayer, &MinecraftEntityId, Option<&Dead>)>,
)> = SystemState::new(ecs);
let (mut commands, mut query) = system_state.get_mut(ecs);
let (local_player, entity_id, dead) = query.get_mut(player_entity).unwrap();
if **entity_id == p.player_id && dead.is_none() {
commands.entity(player_entity).insert(Dead);
let local_player = local_player_query.get(player_entity).unwrap();
local_player
.tx
.send(Event::Death(Some(Arc::new(p.clone()))))
@ -663,6 +753,10 @@ fn handle_packets(
ClientboundGamePacket::ResourcePack(_) => {}
ClientboundGamePacket::Respawn(p) => {
debug!("Got respawn packet {:?}", p);
let mut system_state: SystemState<Commands> = SystemState::new(ecs);
let mut commands = system_state.get(ecs);
// Remove the Dead marker component from the player.
commands.entity(player_entity).remove::<Dead>();
}

View file

@ -25,10 +25,9 @@ impl bevy_app::Plugin for Plugin {
app.add_fixed_timestep_system_set(
"tick",
0,
SystemSet::new()
.with_system(tick_execute_path)
.with_system(goto_listener),
);
SystemSet::new().with_system(tick_execute_path),
)
.add_system(goto_listener);
}
}