mirror of
https://github.com/mat-1/azalea.git
synced 2025-08-02 06:16:04 +00:00
add Loaded component and fix clamping look direction
This commit is contained in:
parent
51963990bc
commit
83cce23614
5 changed files with 86 additions and 66 deletions
|
@ -22,8 +22,9 @@ use azalea_auth::{game_profile::GameProfile, sessionserver::ClientSessionServerE
|
|||
use azalea_chat::FormattedText;
|
||||
use azalea_core::Vec3;
|
||||
use azalea_entity::{
|
||||
indexing::EntityIdIndex, metadata::Health, EntityPlugin, EntityUpdateSet, EyeHeight,
|
||||
LocalEntity, Position,
|
||||
indexing::{EntityIdIndex, Loaded},
|
||||
metadata::Health,
|
||||
EntityPlugin, EntityUpdateSet, EyeHeight, LocalEntity, Position,
|
||||
};
|
||||
use azalea_physics::PhysicsPlugin;
|
||||
use azalea_protocol::{
|
||||
|
@ -316,6 +317,7 @@ impl Client {
|
|||
attack: attack::AttackBundle::default(),
|
||||
|
||||
_local: LocalEntity,
|
||||
_loaded: Loaded,
|
||||
});
|
||||
|
||||
let client = Client::new(
|
||||
|
@ -634,6 +636,7 @@ pub struct JoinedClientBundle {
|
|||
pub attack: attack::AttackBundle,
|
||||
|
||||
pub _local: LocalEntity,
|
||||
pub _loaded: Loaded,
|
||||
}
|
||||
|
||||
pub struct AzaleaPlugin;
|
||||
|
|
|
@ -388,7 +388,7 @@ impl Client {
|
|||
|
||||
/// An event sent when the client starts walking. This does not get sent for
|
||||
/// non-local entities.
|
||||
#[derive(Event)]
|
||||
#[derive(Event, Debug)]
|
||||
pub struct StartWalkEvent {
|
||||
pub entity: Entity,
|
||||
pub direction: WalkDirection,
|
||||
|
|
|
@ -76,6 +76,14 @@ impl Debug for EntityUuidIndex {
|
|||
}
|
||||
}
|
||||
|
||||
/// A marker component for entities that are in the world and aren't temporary
|
||||
/// duplicates of other ones. This is meant to be used as a query filter
|
||||
/// `Added<Loaded>` (since if you do `Added` with another component it might
|
||||
/// trigger multiple times when in a swarm due to how entities are handled for
|
||||
/// swarms).
|
||||
#[derive(Component)]
|
||||
pub struct Loaded;
|
||||
|
||||
/// Remove new entities that have the same id as an existing entity, and
|
||||
/// increase the reference counts.
|
||||
///
|
||||
|
@ -86,7 +94,7 @@ impl Debug for EntityUuidIndex {
|
|||
pub fn deduplicate_entities(
|
||||
mut commands: Commands,
|
||||
mut query: Query<
|
||||
(Entity, &MinecraftEntityId, &InstanceName),
|
||||
(Entity, &MinecraftEntityId, &InstanceName, Option<&Loaded>),
|
||||
(Changed<MinecraftEntityId>, Without<LocalEntity>),
|
||||
>,
|
||||
mut loaded_by_query: Query<&mut LoadedBy>,
|
||||
|
@ -94,43 +102,51 @@ pub fn deduplicate_entities(
|
|||
instance_container: Res<InstanceContainer>,
|
||||
) {
|
||||
// if this entity already exists, remove it and keep the old one
|
||||
for (new_entity, id, world_name) in query.iter_mut() {
|
||||
if let Some(world_lock) = instance_container.get(world_name) {
|
||||
let world = world_lock.write();
|
||||
if let Some(old_entity) = world.entity_by_id.get(id) {
|
||||
if old_entity == &new_entity {
|
||||
continue;
|
||||
}
|
||||
for (new_entity, id, world_name, loaded) in query.iter_mut() {
|
||||
let Some(world_lock) = instance_container.get(world_name) else {
|
||||
error!("Entity was inserted into a world that doesn't exist.");
|
||||
continue;
|
||||
};
|
||||
let world = world_lock.write();
|
||||
let Some(old_entity) = world.entity_by_id.get(id) else {
|
||||
// not in index yet, so it's good
|
||||
if loaded.is_none() {
|
||||
commands.entity(new_entity).insert(Loaded);
|
||||
}
|
||||
continue;
|
||||
};
|
||||
if old_entity == &new_entity {
|
||||
if loaded.is_none() {
|
||||
commands.entity(new_entity).insert(Loaded);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// this entity already exists!!! remove the one we just added but increase
|
||||
// the reference count
|
||||
let new_loaded_by = loaded_by_query
|
||||
.get(new_entity)
|
||||
.expect("Entities should always have the LoadedBy component ({new_entity:?} did not)")
|
||||
.clone();
|
||||
// this entity already exists!!! remove the one we just added but increase
|
||||
// the reference count
|
||||
let new_loaded_by = loaded_by_query
|
||||
.get(new_entity)
|
||||
.expect("Entities should always have the LoadedBy component ({new_entity:?} did not)")
|
||||
.clone();
|
||||
|
||||
// update the `EntityIdIndex`s of the local players that have this entity loaded
|
||||
for local_player in new_loaded_by.iter() {
|
||||
let mut entity_id_index = entity_id_index_query
|
||||
// update the `EntityIdIndex`s of the local players that have this entity loaded
|
||||
for local_player in new_loaded_by.iter() {
|
||||
let mut entity_id_index = entity_id_index_query
|
||||
.get_mut(*local_player)
|
||||
.expect("Local players should always have the EntityIdIndex component ({local_player:?} did not)");
|
||||
entity_id_index.insert(*id, *old_entity);
|
||||
}
|
||||
|
||||
let old_loaded_by = loaded_by_query.get_mut(*old_entity);
|
||||
// merge them if possible
|
||||
if let Ok(mut old_loaded_by) = old_loaded_by {
|
||||
old_loaded_by.extend(new_loaded_by.iter());
|
||||
}
|
||||
commands.entity(new_entity).despawn();
|
||||
info!(
|
||||
"Entity with id {id:?} / {new_entity:?} already existed in the world, merging it with {old_entity:?}"
|
||||
);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
error!("Entity was inserted into a world that doesn't exist.");
|
||||
entity_id_index.insert(*id, *old_entity);
|
||||
}
|
||||
|
||||
let old_loaded_by = loaded_by_query.get_mut(*old_entity);
|
||||
// merge them if possible
|
||||
if let Ok(mut old_loaded_by) = old_loaded_by {
|
||||
old_loaded_by.extend(new_loaded_by.iter());
|
||||
}
|
||||
commands.entity(new_entity).despawn();
|
||||
info!(
|
||||
"Entity with id {id:?} / {new_entity:?} already existed in the world, merging it with {old_entity:?}"
|
||||
);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -147,23 +163,24 @@ pub fn deduplicate_local_entities(
|
|||
) {
|
||||
// if this entity already exists, remove the old one
|
||||
for (new_entity, id, world_name) in query.iter_mut() {
|
||||
if let Some(world_lock) = instance_container.get(world_name) {
|
||||
let world = world_lock.write();
|
||||
if let Some(old_entity) = world.entity_by_id.get(id) {
|
||||
if old_entity == &new_entity {
|
||||
// lol
|
||||
continue;
|
||||
}
|
||||
|
||||
commands.entity(*old_entity).despawn();
|
||||
debug!(
|
||||
"Added local entity {id:?} / {new_entity:?} but already existed in world as {old_entity:?}, despawning {old_entity:?}"
|
||||
);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
let Some(world_lock) = instance_container.get(world_name) else {
|
||||
error!("Entity was inserted into a world that doesn't exist.");
|
||||
continue;
|
||||
};
|
||||
let world = world_lock.write();
|
||||
let Some(old_entity) = world.entity_by_id.get(id) else {
|
||||
continue;
|
||||
};
|
||||
if old_entity == &new_entity {
|
||||
// lol
|
||||
continue;
|
||||
}
|
||||
|
||||
commands.entity(*old_entity).despawn();
|
||||
debug!(
|
||||
"Added local entity {id:?} / {new_entity:?} but already existed in world as {old_entity:?}, despawning {old_entity:?}"
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -129,7 +129,7 @@ pub struct LoadedBy(pub HashSet<Entity>);
|
|||
|
||||
pub fn clamp_look_direction(mut query: Query<&mut LookDirection>) {
|
||||
for mut look_direction in &mut query {
|
||||
look_direction.y_rot %= 360.0;
|
||||
look_direction.y_rot = look_direction.y_rot.rem_euclid(360.0);
|
||||
look_direction.x_rot = look_direction.x_rot.clamp(-90.0, 90.0) % 360.0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -164,17 +164,17 @@ async fn handle(mut bot: Client, event: Event, _state: State) -> anyhow::Result<
|
|||
println!("inventory: {:?}", bot.menu());
|
||||
}
|
||||
"findblock" => {
|
||||
let target_pos = bot
|
||||
.world()
|
||||
.read()
|
||||
.find_block(bot.position(), &azalea::Block::DiamondBlock.into());
|
||||
let target_pos = bot.world().read().find_block(
|
||||
bot.position(),
|
||||
&azalea::registry::Block::DiamondBlock.into(),
|
||||
);
|
||||
bot.chat(&format!("target_pos: {target_pos:?}",));
|
||||
}
|
||||
"gotoblock" => {
|
||||
let target_pos = bot
|
||||
.world()
|
||||
.read()
|
||||
.find_block(bot.position(), &azalea::Block::DiamondBlock.into());
|
||||
let target_pos = bot.world().read().find_block(
|
||||
bot.position(),
|
||||
&azalea::registry::Block::DiamondBlock.into(),
|
||||
);
|
||||
if let Some(target_pos) = target_pos {
|
||||
// +1 to stand on top of the block
|
||||
bot.goto(BlockPosGoal::from(target_pos.up(1)));
|
||||
|
@ -183,10 +183,10 @@ async fn handle(mut bot: Client, event: Event, _state: State) -> anyhow::Result<
|
|||
}
|
||||
}
|
||||
"mineblock" => {
|
||||
let target_pos = bot
|
||||
.world()
|
||||
.read()
|
||||
.find_block(bot.position(), &azalea::Block::DiamondBlock.into());
|
||||
let target_pos = bot.world().read().find_block(
|
||||
bot.position(),
|
||||
&azalea::registry::Block::DiamondBlock.into(),
|
||||
);
|
||||
if let Some(target_pos) = target_pos {
|
||||
// +1 to stand on top of the block
|
||||
bot.chat("ok mining diamond block");
|
||||
|
@ -201,7 +201,7 @@ async fn handle(mut bot: Client, event: Event, _state: State) -> anyhow::Result<
|
|||
let target_pos = bot
|
||||
.world()
|
||||
.read()
|
||||
.find_block(bot.position(), &azalea::Block::Lever.into());
|
||||
.find_block(bot.position(), &azalea::registry::Block::Lever.into());
|
||||
let Some(target_pos) = target_pos else {
|
||||
bot.chat("no lever found");
|
||||
return Ok(());
|
||||
|
@ -218,7 +218,7 @@ async fn handle(mut bot: Client, event: Event, _state: State) -> anyhow::Result<
|
|||
let target_pos = bot
|
||||
.world()
|
||||
.read()
|
||||
.find_block(bot.position(), &azalea::Block::Chest.into());
|
||||
.find_block(bot.position(), &azalea::registry::Block::Chest.into());
|
||||
let Some(target_pos) = target_pos else {
|
||||
bot.chat("no chest found");
|
||||
return Ok(());
|
||||
|
|
Loading…
Add table
Reference in a new issue