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

add Event::Spawn

This commit is contained in:
mat 2025-03-20 03:30:57 +00:00
parent 13d5cbed1f
commit 5c7332b469
4 changed files with 40 additions and 9 deletions

View file

@ -5,7 +5,7 @@ use std::sync::Arc;
use azalea_chat::FormattedText; use azalea_chat::FormattedText;
use azalea_core::tick::GameTick; use azalea_core::tick::GameTick;
use azalea_entity::Dead; use azalea_entity::{Dead, InLoadedChunk};
use azalea_protocol::packets::game::{ use azalea_protocol::packets::game::{
ClientboundGamePacket, c_player_combat_kill::ClientboundPlayerCombatKill, ClientboundGamePacket, c_player_combat_kill::ClientboundPlayerCombatKill,
}; };
@ -13,10 +13,11 @@ use azalea_world::{InstanceName, MinecraftEntityId};
use bevy_app::{App, Plugin, PreUpdate, Update}; use bevy_app::{App, Plugin, PreUpdate, Update};
use bevy_ecs::{ use bevy_ecs::{
component::Component, component::Component,
entity::Entity,
event::EventReader, event::EventReader,
query::{Added, With}, query::{Added, With, Without},
schedule::IntoSystemConfigs, schedule::IntoSystemConfigs,
system::Query, system::{Commands, Query},
}; };
use derive_more::{Deref, DerefMut}; use derive_more::{Deref, DerefMut};
use tokio::sync::mpsc; use tokio::sync::mpsc;
@ -65,11 +66,23 @@ pub enum Event {
/// information with `Client::set_client_information`, so the packet /// information with `Client::set_client_information`, so the packet
/// doesn't have to be sent twice. /// doesn't have to be sent twice.
/// ///
/// You may want to use [`Event::Login`] instead to wait for the bot to be /// You may want to use [`Event::Spawn`] instead to wait for the bot to be
/// in the world. /// in the world.
Init, Init,
/// The client is now in the world. Fired when we receive a login packet. /// Fired when we receive a login packet, which is after [`Event::Init`] but
/// before [`Event::Spawn`]. You usually want [`Event::Spawn`] instead.
///
/// Your position will be [`Vec3::ZERO`] immediately after you receive this
/// packet, but it'll be ready by the time you get [`Event::Spawn`].
///
/// [`Vec3::ZERO`]: azalea_core::position::Vec3::ZERO
Login, Login,
/// Fired when the player fully spawns into the world and is ready to
/// interact with it.
///
/// This is usually the event you should listen for when waiting for the bot
/// to be ready.
Spawn,
/// A chat message was sent in the game chat. /// A chat message was sent in the game chat.
Chat(ChatPacket), Chat(ChatPacket),
/// Happens 20 times per second, but only when the world is loaded. /// Happens 20 times per second, but only when the world is loaded.
@ -125,6 +138,7 @@ impl Plugin for EventsPlugin {
( (
chat_listener, chat_listener,
login_listener, login_listener,
spawn_listener,
packet_listener, packet_listener,
add_player_listener, add_player_listener,
update_player_listener, update_player_listener,
@ -156,6 +170,23 @@ pub fn login_listener(query: Query<&LocalPlayerEvents, Added<MinecraftEntityId>>
} }
} }
/// A unit struct component that indicates that the entity has sent
/// [`Event::Spawn`].
///
/// This is just used internally by the [`spawn_listener`] system to avoid
/// sending the event twice for the same client.
#[derive(Component)]
pub struct SentSpawnEvent;
pub fn spawn_listener(
query: Query<(Entity, &LocalPlayerEvents), (Added<InLoadedChunk>, Without<SentSpawnEvent>)>,
mut commands: Commands,
) {
for (entity, local_player_events) in &query {
let _ = local_player_events.send(Event::Spawn);
commands.entity(entity).insert(SentSpawnEvent);
}
}
pub fn chat_listener(query: Query<&LocalPlayerEvents>, mut events: EventReader<ChatReceivedEvent>) { pub fn chat_listener(query: Query<&LocalPlayerEvents>, mut events: EventReader<ChatReceivedEvent>) {
for event in events.read() { for event in events.read() {
let local_player_events = query let local_player_events = query

View file

@ -1482,7 +1482,7 @@ impl GamePacketHandler<'_> {
// this resets a bunch of our components like physics and stuff // this resets a bunch of our components like physics and stuff
let entity_bundle = EntityBundle::new( let entity_bundle = EntityBundle::new(
game_profile.uuid, game_profile.uuid,
Vec3::default(), Vec3::ZERO,
azalea_registry::EntityKind::Player, azalea_registry::EntityKind::Player,
new_instance_name, new_instance_name,
); );

View file

@ -50,7 +50,7 @@ pub fn move_relative(
pub fn input_vector(direction: &LookDirection, speed: f32, acceleration: &Vec3) -> Vec3 { pub fn input_vector(direction: &LookDirection, speed: f32, acceleration: &Vec3) -> Vec3 {
let distance = acceleration.length_squared(); let distance = acceleration.length_squared();
if distance < 1.0E-7 { if distance < 1.0E-7 {
return Vec3::default(); return Vec3::ZERO;
} }
let acceleration = if distance > 1.0 { let acceleration = if distance > 1.0 {
acceleration.normalize() acceleration.normalize()
@ -307,7 +307,7 @@ pub struct Physics {
impl Physics { impl Physics {
pub fn new(dimensions: EntityDimensions, pos: Vec3) -> Self { pub fn new(dimensions: EntityDimensions, pos: Vec3) -> Self {
Self { Self {
velocity: Vec3::default(), velocity: Vec3::ZERO,
vec_delta_codec: VecDeltaCodec::new(pos), vec_delta_codec: VecDeltaCodec::new(pos),
old_position: pos, old_position: pos,

View file

@ -109,7 +109,7 @@ fn update_fluid_height_and_do_fluid_pushing(
let mut min_height_touching = 0.; let mut min_height_touching = 0.;
let is_entity_pushable_by_fluid = true; let is_entity_pushable_by_fluid = true;
let mut touching_fluid = false; let mut touching_fluid = false;
let mut additional_player_delta = Vec3::default(); let mut additional_player_delta = Vec3::ZERO;
let mut num_fluids_being_touched = 0; let mut num_fluids_being_touched = 0;
for cur_x in min_x..max_x { for cur_x in min_x..max_x {