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

everything compiles

This commit is contained in:
Ubuntu 2023-01-20 19:01:52 +00:00
parent 8921ae4887
commit 8ea3d728c1
8 changed files with 76 additions and 35 deletions

View file

@ -4,7 +4,9 @@ use uuid::Uuid;
#[derive(McBuf, Debug, Clone, Default)] #[derive(McBuf, Debug, Clone, Default)]
pub struct GameProfile { pub struct GameProfile {
/// The UUID of the player.
pub uuid: Uuid, pub uuid: Uuid,
/// The username of the player.
pub name: String, pub name: String,
pub properties: HashMap<String, ProfilePropertyValue>, pub properties: HashMap<String, ProfilePropertyValue>,
} }

View file

@ -153,7 +153,7 @@ impl Client {
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
pub async fn chat(&self, message: &str) { pub fn chat(&self, message: &str) {
if let Some(command) = message.strip_prefix('/') { if let Some(command) = message.strip_prefix('/') {
self.send_command_packet(command); self.send_command_packet(command);
} else { } else {

View file

@ -1,7 +1,7 @@
pub use crate::chat::ChatPacket; pub use crate::chat::ChatPacket;
use crate::{ use crate::{
local_player::{ local_player::{
death_event, send_tick_event, update_in_loaded_chunk, LocalPlayer, PhysicsState, death_event, send_tick_event, update_in_loaded_chunk, LocalPlayer, PhysicsState, GameProfileComponent,
}, },
movement::{local_player_ai_step, send_position, sprint_listener, walk_listener}, movement::{local_player_ai_step, send_position, sprint_listener, walk_listener},
packet_handling::{self, PacketHandlerPlugin}, packet_handling::{self, PacketHandlerPlugin},
@ -232,7 +232,6 @@ impl Client {
let mut local_player = crate::local_player::LocalPlayer::new( let mut local_player = crate::local_player::LocalPlayer::new(
entity, entity,
game_profile,
packet_writer_sender, packet_writer_sender,
// default to an empty world, it'll be set correctly later when we // default to an empty world, it'll be set correctly later when we
// get the login packet // get the login packet
@ -258,6 +257,7 @@ impl Client {
ecs.entity_mut(entity).insert(( ecs.entity_mut(entity).insert((
local_player, local_player,
packet_receiver, packet_receiver,
GameProfileComponent(game_profile),
PhysicsState::default(), PhysicsState::default(),
Local, Local,
)); ));

View file

@ -25,12 +25,34 @@ impl Client {
/// ///
/// You can then use [`Self::map_entity`] to get components from this /// You can then use [`Self::map_entity`] to get components from this
/// entity. /// entity.
///
/// # Example
/// Note that this will very likely change in the future.
/// ```
/// let entity = bot.entity_by::<With<Player>, (&GameProfileComponent,)>(
/// |profile: &&GameProfileComponent| profile.name == sender,
/// );
/// if let Some(entity) = entity {
/// let position = bot.entity_components::<Position>(entity);
/// }
/// ```
pub fn entity_by<F: ReadOnlyWorldQuery, Q: ReadOnlyWorldQuery>( pub fn entity_by<F: ReadOnlyWorldQuery, Q: ReadOnlyWorldQuery>(
&mut self, &mut self,
predicate: impl EntityPredicate<Q, F>, predicate: impl EntityPredicate<Q, F>,
) -> Option<Entity> { ) -> Option<Entity> {
predicate.find(self.ecs.clone()) predicate.find(self.ecs.clone())
} }
/// Get a component from an entity. Note that this will return an owned type
/// (i.e. not a reference) so it may be expensive for larger types.
pub fn entity_components<Q: Component + Clone>(&mut self, entity: Entity) -> Q {
let mut ecs = self.ecs.lock();
let mut q = ecs.query::<&Q>();
let components = q
.get(&ecs, entity)
.expect("Entity components must be present in Client::entity)components.");
components.clone()
}
} }
pub trait EntityPredicate<Q: ReadOnlyWorldQuery, Filter: ReadOnlyWorldQuery> { pub trait EntityPredicate<Q: ReadOnlyWorldQuery, Filter: ReadOnlyWorldQuery> {

View file

@ -26,7 +26,7 @@ mod plugins;
pub use account::Account; pub use account::Account;
pub use bevy_ecs as ecs; pub use bevy_ecs as ecs;
pub use client::{start_ecs, ChatPacket, Client, ClientInformation, Event, JoinError}; pub use client::{start_ecs, ChatPacket, Client, ClientInformation, Event, JoinError};
pub use local_player::LocalPlayer; pub use local_player::{GameProfileComponent, LocalPlayer};
pub use movement::{SprintDirection, StartSprintEvent, StartWalkEvent, WalkDirection}; pub use movement::{SprintDirection, StartSprintEvent, StartWalkEvent, WalkDirection};
pub use player::PlayerInfo; pub use player::PlayerInfo;
pub use plugins::{Plugin, PluginState, PluginStates, Plugins}; pub use plugins::{Plugin, PluginState, PluginStates, Plugins};

View file

@ -8,6 +8,7 @@ use azalea_world::{
EntityInfos, PartialWorld, World, EntityInfos, PartialWorld, World,
}; };
use bevy_ecs::{component::Component, query::Added, system::Query}; use bevy_ecs::{component::Component, query::Added, system::Query};
use derive_more::{Deref, DerefMut};
use log::warn; use log::warn;
use parking_lot::RwLock; use parking_lot::RwLock;
use thiserror::Error; use thiserror::Error;
@ -19,8 +20,6 @@ use crate::{ClientInformation, Event, PlayerInfo, WalkDirection};
/// A player that you control that is currently in a Minecraft server. /// A player that you control that is currently in a Minecraft server.
#[derive(Component)] #[derive(Component)]
pub struct LocalPlayer { pub struct LocalPlayer {
pub profile: GameProfile,
pub packet_writer: mpsc::UnboundedSender<ServerboundGamePacket>, pub packet_writer: mpsc::UnboundedSender<ServerboundGamePacket>,
pub client_information: ClientInformation, pub client_information: ClientInformation,
@ -59,6 +58,14 @@ pub struct PhysicsState {
pub left_impulse: f32, pub left_impulse: f32,
} }
/// A component only present in players that contains the [`GameProfile`] (which
/// you can use to get a player's name).
///
/// Note that it's possible for this to be missing in a player if the server
/// never sent the player info for them (though this is uncommon).
#[derive(Component, Clone, Debug, Deref, DerefMut)]
pub struct GameProfileComponent(pub GameProfile);
/// Marks a [`LocalPlayer`] that's in a loaded chunk. This is updated at the /// Marks a [`LocalPlayer`] that's in a loaded chunk. This is updated at the
/// beginning of every tick. /// beginning of every tick.
#[derive(Component)] #[derive(Component)]
@ -71,7 +78,6 @@ impl LocalPlayer {
/// defaults, otherwise use [`Client::join`]. /// defaults, otherwise use [`Client::join`].
pub fn new( pub fn new(
entity: Entity, entity: Entity,
profile: GameProfile,
packet_writer: mpsc::UnboundedSender<ServerboundGamePacket>, packet_writer: mpsc::UnboundedSender<ServerboundGamePacket>,
world: Arc<RwLock<World>>, world: Arc<RwLock<World>>,
tx: mpsc::UnboundedSender<Event>, tx: mpsc::UnboundedSender<Event>,
@ -79,8 +85,6 @@ impl LocalPlayer {
let client_information = ClientInformation::default(); let client_information = ClientInformation::default();
LocalPlayer { LocalPlayer {
profile,
packet_writer, packet_writer,
client_information: ClientInformation::default(), client_information: ClientInformation::default(),

View file

@ -31,7 +31,10 @@ use log::{debug, error, trace, warn};
use parking_lot::Mutex; use parking_lot::Mutex;
use tokio::sync::mpsc; use tokio::sync::mpsc;
use crate::{local_player::LocalPlayer, ChatPacket, ClientInformation, Event, PlayerInfo}; use crate::{
local_player::{GameProfileComponent, LocalPlayer},
ChatPacket, ClientInformation, Event, PlayerInfo,
};
pub struct PacketHandlerPlugin; pub struct PacketHandlerPlugin;
@ -89,13 +92,13 @@ fn handle_packets(ecs: &mut bevy_ecs::world::World) {
let mut system_state: SystemState<( let mut system_state: SystemState<(
Commands, Commands,
Query<&mut LocalPlayer>, Query<(&mut LocalPlayer, &GameProfileComponent)>,
ResMut<WorldContainer>, ResMut<WorldContainer>,
ResMut<EntityInfos>, ResMut<EntityInfos>,
)> = SystemState::new(ecs); )> = SystemState::new(ecs);
let (mut commands, mut query, mut world_container, mut entity_infos) = let (mut commands, mut query, mut world_container, mut entity_infos) =
system_state.get_mut(ecs); system_state.get_mut(ecs);
let mut local_player = query.get_mut(player_entity).unwrap(); let (mut local_player, game_profile) = query.get_mut(player_entity).unwrap();
{ {
// TODO: have registry_holder be a struct because this sucks rn // TODO: have registry_holder be a struct because this sucks rn
@ -172,7 +175,7 @@ fn handle_packets(ecs: &mut bevy_ecs::world::World) {
let player_bundle = PlayerBundle { let player_bundle = PlayerBundle {
entity: EntityBundle::new( entity: EntityBundle::new(
local_player.profile.uuid, game_profile.uuid,
Vec3::default(), Vec3::default(),
azalea_registry::EntityKind::Player, azalea_registry::EntityKind::Player,
world_name, world_name,
@ -527,6 +530,7 @@ fn handle_packets(ecs: &mut bevy_ecs::world::World) {
LoadedBy(HashSet::from([player_entity])), LoadedBy(HashSet::from([player_entity])),
bundle, bundle,
)); ));
println!("spawned player entity: {:?}", spawned.id()); println!("spawned player entity: {:?}", spawned.id());
} else { } else {
warn!("got add player packet but we haven't gotten a login packet yet"); warn!("got add player packet but we haven't gotten a login packet yet");

View file

@ -5,7 +5,7 @@ use azalea::entity::metadata::Player;
use azalea::entity::Position; use azalea::entity::Position;
use azalea::pathfinder::BlockPosGoal; use azalea::pathfinder::BlockPosGoal;
// use azalea::ClientInformation; // use azalea::ClientInformation;
use azalea::{prelude::*, BlockPos, Swarm, SwarmEvent, WalkDirection}; use azalea::{prelude::*, BlockPos, GameProfileComponent, Swarm, SwarmEvent, WalkDirection};
use azalea::{Account, Client, Event}; use azalea::{Account, Client, Event};
use azalea_protocol::packets::game::serverbound_client_command_packet::ServerboundClientCommandPacket; use azalea_protocol::packets::game::serverbound_client_command_packet::ServerboundClientCommandPacket;
use std::time::Duration; use std::time::Duration;
@ -103,28 +103,37 @@ async fn handle(mut bot: Client, event: Event, _state: State) -> anyhow::Result<
// .iter(&mut ecs) // .iter(&mut ecs)
// .find(|e| e.name() == Some(sender)); // .find(|e| e.name() == Some(sender));
// let entity = bot.entity_by::<With<Player>>(|name: &Name| name == sender); // let entity = bot.entity_by::<With<Player>>(|name: &Name| name == sender);
// let entity = bot.entity_by(|name: &Name| name == sender); let entity = bot.entity_by::<With<Player>, (&GameProfileComponent,)>(
let entity = bot.entity_by::<With<Player>, (&Position,)>(|pos: &&Position| true); |profile: &&GameProfileComponent| profile.name == sender,
);
if let Some(entity) = entity { if let Some(entity) = entity {
// if m.content() == "goto" { match m.content().as_str() {
// let target_pos_vec3 = entity.pos(); "goto" => {
// let target_pos: BlockPos = target_pos_vec3.into(); let entity_pos = bot.entity_components::<Position>(entity);
// bot.goto(BlockPosGoal::from(target_pos)); let target_pos: BlockPos = entity_pos.into();
// } else if m.content() == "look" { bot.goto(BlockPosGoal::from(target_pos));
// let target_pos_vec3 = entity.pos(); }
// let target_pos: BlockPos = target_pos_vec3.into(); "look" => {
// println!("target_pos: {:?}", target_pos); let entity_pos = bot.entity_components::<Position>(entity);
// bot.look_at(target_pos.center()); let target_pos: BlockPos = entity_pos.into();
// } else if m.content() == "jump" { println!("target_pos: {:?}", target_pos);
// bot.set_jumping(true); bot.look_at(target_pos.center());
// } else if m.content() == "walk" { }
// bot.walk(WalkDirection::Forward); "jump" => {
// } else if m.content() == "stop" { bot.set_jumping(true);
// bot.set_jumping(false); }
// bot.walk(WalkDirection::None); "walk" => {
// } else if m.content() == "lag" { bot.walk(WalkDirection::Forward);
// std::thread::sleep(Duration::from_millis(1000)); }
// } "stop" => {
bot.set_jumping(false);
bot.walk(WalkDirection::None);
}
"lag" => {
std::thread::sleep(Duration::from_millis(1000));
}
_ => {}
}
} }
} }
Event::Death(_) => { Event::Death(_) => {