diff options
Diffstat (limited to 'azalea')
| -rw-r--r-- | azalea/examples/testbot/commands/debug.rs | 22 | ||||
| -rw-r--r-- | azalea/src/client_impl/entity_query.rs | 54 | ||||
| -rw-r--r-- | azalea/src/client_impl/mod.rs | 47 | ||||
| -rw-r--r-- | azalea/src/entity_ref/mod.rs | 4 | ||||
| -rw-r--r-- | azalea/src/entity_ref/shared_impls.rs | 24 | ||||
| -rw-r--r-- | azalea/src/events.rs | 4 | ||||
| -rw-r--r-- | azalea/src/nearest_entity.rs | 46 | ||||
| -rw-r--r-- | azalea/src/pathfinder/debug.rs | 8 | ||||
| -rw-r--r-- | azalea/src/pathfinder/extras/utils.rs | 4 | ||||
| -rw-r--r-- | azalea/src/pathfinder/mod.rs | 79 | ||||
| -rw-r--r-- | azalea/src/pathfinder/moves/mod.rs | 21 | ||||
| -rw-r--r-- | azalea/src/pathfinder/simulation.rs | 56 | ||||
| -rw-r--r-- | azalea/src/pathfinder/world.rs | 14 | ||||
| -rw-r--r-- | azalea/src/swarm/builder.rs | 6 | ||||
| -rw-r--r-- | azalea/src/swarm/chat.rs | 12 | ||||
| -rw-r--r-- | azalea/src/swarm/events.rs | 4 | ||||
| -rw-r--r-- | azalea/src/swarm/mod.rs | 4 |
17 files changed, 197 insertions, 212 deletions
diff --git a/azalea/examples/testbot/commands/debug.rs b/azalea/examples/testbot/commands/debug.rs index 1f9d5e5d..57d9ff1f 100644 --- a/azalea/examples/testbot/commands/debug.rs +++ b/azalea/examples/testbot/commands/debug.rs @@ -15,7 +15,7 @@ use azalea::{ use azalea_core::hit_result::HitResult; use azalea_entity::{EntityKindComponent, metadata}; use azalea_inventory::components::MaxStackSize; -use azalea_world::InstanceContainer; +use azalea_world::Worlds; use bevy_app::AppExit; use bevy_ecs::{message::Messages, query::With, world::EntityRef}; use parking_lot::Mutex; @@ -331,16 +331,16 @@ pub fn register(commands: &mut CommandDispatcher<Mutex<CommandSource>>) { // info.layout().size()).unwrap(); match name.as_ref() { - "azalea_world::container::InstanceContainer" => { - let instance_container = ecs.resource::<InstanceContainer>(); + "azalea_world::container::Worlds" => { + let worlds = ecs.resource::<Worlds>(); - for (instance_name, instance) in &instance_container.instances { - writeln!(report, "- Name: {instance_name}").unwrap(); - writeln!(report, "- Reference count: {}", instance.strong_count()) + for (world_name, world) in &worlds.map { + writeln!(report, "- Name: {world_name}").unwrap(); + writeln!(report, "- Reference count: {}", world.strong_count()) .unwrap(); - if let Some(instance) = instance.upgrade() { - let instance = instance.read(); - let strong_chunks = instance + if let Some(world) = world.upgrade() { + let world = world.read(); + let strong_chunks = world .chunks .map .iter() @@ -350,13 +350,13 @@ pub fn register(commands: &mut CommandDispatcher<Mutex<CommandSource>>) { report, "- Chunks: {} strongly referenced, {} in map", strong_chunks, - instance.chunks.map.len() + world.chunks.map.len() ) .unwrap(); writeln!( report, "- Entities: {}", - instance.entities_by_chunk.len() + world.entities_by_chunk.len() ) .unwrap(); } diff --git a/azalea/src/client_impl/entity_query.rs b/azalea/src/client_impl/entity_query.rs index 44fbe9e8..27c3aa9a 100644 --- a/azalea/src/client_impl/entity_query.rs +++ b/azalea/src/client_impl/entity_query.rs @@ -2,7 +2,7 @@ use std::{any, sync::Arc}; use azalea_core::position::Vec3; use azalea_entity::Position; -use azalea_world::InstanceName; +use azalea_world::WorldName; use bevy_ecs::{ component::Component, entity::Entity, @@ -44,9 +44,9 @@ impl Client { /// # Examples /// /// ``` - /// # use azalea_world::InstanceName; + /// # use azalea_world::WorldName; /// # fn example(client: &azalea::Client) { - /// let world_name = client.component::<InstanceName>(); + /// let world_name = client.component::<WorldName>(); /// # } pub fn component<T: Component>(&self) -> MappedRwLockReadGuard<'_, T> { self.get_component::<T>().unwrap_or_else(|| { @@ -150,9 +150,9 @@ impl Client { /// Quickly returns an [`EntityRef`] for an arbitrary entity that /// matches the given predicate function that is in the same - /// [`Instance`] as the client. + /// [`World`] as the client. /// - /// [`Instance`]: azalea_world::Instance + /// [`World`]: azalea_world::World pub fn any_entity_by<Q: QueryData, F: QueryFilter>( &self, predicate: impl EntityPredicate<Q, F>, @@ -162,7 +162,7 @@ impl Client { } /// Quickly returns a lightweight [`Entity`] for an arbitrary entity that /// matches the given predicate function that is in the same - /// [`Instance`] as the client. + /// [`World`] as the client. /// /// To get an [`EntityRef`], consider using [`Self::any_entity_by`] /// instead. @@ -184,13 +184,13 @@ impl Client { /// # } /// ``` /// - /// [`Instance`]: azalea_world::Instance + /// [`World`]: azalea_world::World pub fn any_entity_id_by<Q: QueryData, F: QueryFilter>( &self, predicate: impl EntityPredicate<Q, F>, ) -> Option<Entity> { - let instance_name = self.get_component::<InstanceName>()?.clone(); - predicate.find_any(self.ecs.clone(), &instance_name) + let world_name = self.get_component::<WorldName>()?.clone(); + predicate.find_any(self.ecs.clone(), &world_name) } /// Return an [`EntityRef`] for the nearest entity that matches the @@ -225,7 +225,7 @@ impl Client { self.nearest_entity_ids_by(predicate).first().copied() } - /// Returns an array of all [`EntityRef`]s in the instance that match the + /// Returns an array of all [`EntityRef`]s in the world that match the /// predicate, sorted by nearest first. /// /// To only get the nearest entity, consider using @@ -240,7 +240,7 @@ impl Client { .map(|e| self.entity_ref_for(e)) .collect() } - /// Returns an array of all [`Entity`]s in the instance that match the + /// Returns an array of all [`Entity`]s in the world that match the /// predicate, sorted by nearest first. /// /// To only get the nearest entity, consider using @@ -259,18 +259,18 @@ impl Client { &self, predicate: impl EntityPredicate<Q, F>, ) -> Box<[Entity]> { - let (instance_name, position) = { - let Some(instance_name) = self.get_component::<InstanceName>() else { + let (world_name, position) = { + let Some(world_name) = self.get_component::<WorldName>() else { return Box::new([]); }; let Some(position) = self.get_component::<Position>() else { return Box::new([]); }; - (instance_name.clone(), **position) + (world_name.clone(), **position) }; - predicate.find_all_sorted(self.ecs.clone(), &instance_name, position) + predicate.find_all_sorted(self.ecs.clone(), &world_name, position) } /// Get a component from an entity. @@ -316,15 +316,11 @@ impl Client { } pub trait EntityPredicate<Q: QueryData, Filter: QueryFilter> { - fn find_any( - &self, - ecs_lock: Arc<RwLock<World>>, - instance_name: &InstanceName, - ) -> Option<Entity>; + fn find_any(&self, ecs_lock: Arc<RwLock<World>>, world_name: &WorldName) -> Option<Entity>; fn find_all_sorted( &self, ecs_lock: Arc<RwLock<World>>, - instance_name: &InstanceName, + world_name: &WorldName, nearest_to: Vec3, ) -> Box<[Entity]>; } @@ -333,30 +329,26 @@ where F: Fn(ROQueryItem<Q>) -> bool, for<'w, 's> <<Q as QueryData>::ReadOnly as QueryData>::Item<'w, 's>: Copy, { - fn find_any( - &self, - ecs_lock: Arc<RwLock<World>>, - instance_name: &InstanceName, - ) -> Option<Entity> { + fn find_any(&self, ecs_lock: Arc<RwLock<World>>, world_name: &WorldName) -> Option<Entity> { let mut ecs = ecs_lock.write(); - let mut query = ecs.query_filtered::<(Entity, &InstanceName, Q), Filter>(); + let mut query = ecs.query_filtered::<(Entity, &WorldName, Q), Filter>(); query .iter(&ecs) - .find(|(_, e_instance_name, q)| *e_instance_name == instance_name && (self)(*q)) + .find(|(_, e_world_name, q)| *e_world_name == world_name && (self)(*q)) .map(|(e, _, _)| e) } fn find_all_sorted( &self, ecs_lock: Arc<RwLock<World>>, - instance_name: &InstanceName, + world_name: &WorldName, nearest_to: Vec3, ) -> Box<[Entity]> { let mut ecs = ecs_lock.write(); - let mut query = ecs.query_filtered::<(Entity, &InstanceName, &Position, Q), Filter>(); + let mut query = ecs.query_filtered::<(Entity, &WorldName, &Position, Q), Filter>(); let mut entities = query .iter(&ecs) - .filter(|(_, e_instance_name, _, q)| *e_instance_name == instance_name && (self)(*q)) + .filter(|(_, e_world_name, _, q)| *e_world_name == world_name && (self)(*q)) .map(|(e, _, position, _)| (e, Vec3::from(position))) .collect::<Vec<(Entity, Vec3)>>(); diff --git a/azalea/src/client_impl/mod.rs b/azalea/src/client_impl/mod.rs index f884898f..d55e5a38 100644 --- a/azalea/src/client_impl/mod.rs +++ b/azalea/src/client_impl/mod.rs @@ -7,7 +7,7 @@ use azalea_client::{ connection::RawConnection, disconnect::DisconnectEvent, join::{ConnectOpts, StartJoinServerEvent}, - local_player::{Hunger, InstanceHolder, TabList}, + local_player::{Hunger, TabList, WorldHolder}, packet::game::SendGamePacketEvent, player::{GameProfileComponent, PlayerInfo}, start_ecs_runner, @@ -25,13 +25,9 @@ use azalea_protocol::{ resolve::ResolveError, }; use azalea_registry::{DataRegistryKeyRef, identifier::Identifier}; -use azalea_world::{Instance, InstanceName, PartialInstance}; +use azalea_world::{PartialWorld, World, WorldName}; use bevy_app::App; -use bevy_ecs::{ - entity::Entity, - resource::Resource, - world::{Mut, World}, -}; +use bevy_ecs::{entity::Entity, resource::Resource, world::Mut}; use parking_lot::RwLock; use tokio::sync::mpsc; use uuid::Uuid; @@ -67,17 +63,17 @@ pub struct Client { /// A mutually exclusive reference to the entity component system (ECS). /// /// You probably don't need to access this directly. Note that if you're - /// using a shared world (i.e. a swarm), the ECS will contain all entities - /// in all instances/dimensions. + /// using a shared world (i.e. a swarm), the ECS will also contain all + /// entities in all worlds. /// /// You can nearly always use [`Self::component`], [`Self::query_self`], /// [`Self::query_entity`], or another one of those related functions to /// access the ECS instead. - pub ecs: Arc<RwLock<World>>, + pub ecs: Arc<RwLock<bevy_ecs::world::World>>, } pub struct StartClientOpts { - pub ecs_lock: Arc<RwLock<World>>, + pub ecs_lock: Arc<RwLock<bevy_ecs::world::World>>, pub account: Account, pub connect_opts: ConnectOpts, pub event_sender: Option<mpsc::UnboundedSender<Event>>, @@ -144,7 +140,7 @@ impl Client { /// World, and schedule runner function. /// You should only use this if you want to change these fields from the /// defaults, otherwise use [`Client::join`]. - pub fn new(entity: Entity, ecs: Arc<RwLock<World>>) -> Self { + pub fn new(entity: Entity, ecs: Arc<RwLock<bevy_ecs::world::World>>) -> Self { Self { // default our id to 0, it'll be set later entity, @@ -278,15 +274,16 @@ impl Client { f(value) } - /// Get an `RwLock` with a reference to our (potentially shared) world. + /// Get an `RwLock` with a reference to our (potentially shared) Minecraft + /// world. /// - /// This gets the [`Instance`] from the client's [`InstanceHolder`] + /// This gets the [`World`] from the client's [`WorldHolder`] /// component. If it's a normal client, then it'll be the same as the /// world the client has loaded. If the client is using a shared world, /// then the shared world will be a superset of the client's world. - pub fn world(&self) -> Arc<RwLock<Instance>> { - let instance_holder = self.component::<InstanceHolder>(); - instance_holder.instance.clone() + pub fn world(&self) -> Arc<RwLock<World>> { + let world_holder = self.component::<WorldHolder>(); + world_holder.shared.clone() } /// Get an `RwLock` with a reference to the world that this client has @@ -298,15 +295,15 @@ impl Client { /// let world = client.partial_world(); /// let is_0_0_loaded = world.read().chunks.limited_get(&ChunkPos::new(0, 0)).is_some(); /// # } - pub fn partial_world(&self) -> Arc<RwLock<PartialInstance>> { - let instance_holder = self.component::<InstanceHolder>(); - instance_holder.partial_instance.clone() + pub fn partial_world(&self) -> Arc<RwLock<PartialWorld>> { + let world_holder = self.component::<WorldHolder>(); + world_holder.partial.clone() } /// Returns whether we have a received the login packet yet. pub fn logged_in(&self) -> bool { // the login packet tells us the world name - self.query_self::<Option<&InstanceName>, _>(|ins| ins.is_some()) + self.query_self::<Option<&WorldName>, _>(|ins| ins.is_some()) } /// Returns the client as an [`EntityRef`], allowing you to treat it as any @@ -409,8 +406,8 @@ impl Client { /// Call the given function with the client's [`RegistryHolder`]. /// - /// The player's instance (aka world) will be locked during this time, which - /// may result in a deadlock if you try to access the instance again while + /// Note that the player's world will be locked during this time, which may + /// result in a deadlock if you try to access the world again while /// in the function. /// /// [`RegistryHolder`]: azalea_core::registry_holder::RegistryHolder @@ -418,8 +415,8 @@ impl Client { &self, f: impl FnOnce(&azalea_core::registry_holder::RegistryHolder) -> R, ) -> R { - let instance = self.world(); - let registries = &instance.read().registries; + let world = self.world(); + let registries = &world.read().registries; f(registries) } diff --git a/azalea/src/entity_ref/mod.rs b/azalea/src/entity_ref/mod.rs index d604fe00..e09852c1 100644 --- a/azalea/src/entity_ref/mod.rs +++ b/azalea/src/entity_ref/mod.rs @@ -57,9 +57,9 @@ impl EntityRef { /// # Examples /// /// ``` - /// # use azalea_world::InstanceName; + /// # use azalea_world::WorldName; /// # fn example(client: &azalea::Client) { - /// let world_name = client.component::<InstanceName>(); + /// let world_name = client.component::<WorldName>(); /// # } pub fn component<T: Component>(&self) -> MappedRwLockReadGuard<'_, T> { self.client.entity_component(self.entity) diff --git a/azalea/src/entity_ref/shared_impls.rs b/azalea/src/entity_ref/shared_impls.rs index f6aa332e..79396f56 100644 --- a/azalea/src/entity_ref/shared_impls.rs +++ b/azalea/src/entity_ref/shared_impls.rs @@ -2,7 +2,7 @@ use azalea_core::{entity_id::MinecraftEntityId, position::Vec3}; use azalea_entity::{ Attributes, Dead, EntityUuid, Physics, Position, dimensions::EntityDimensions, metadata::Health, }; -use azalea_world::InstanceName; +use azalea_world::WorldName; use uuid::Uuid; use super::EntityRef; @@ -141,21 +141,29 @@ impl_entity_functions! { } Client: - /// Get the name of the instance (world) that the bot is in. + #[deprecated = "renamed to `world_name`."] + EntityRef: + #[deprecated = "renamed to `world_name`."] + pub fn instance_name(&self) -> WorldName { + self.world_name() + } + + Client: + /// Get the name of the world that the bot is in. /// /// This can be used to check if the client is in the same world as another /// entity. - #[doc(alias("world_name", "dimension_name"))] + #[doc(alias("dimension_name"))] EntityRef: - /// Get the name of the instance (world) that the entity is in. + /// Get the name of the world that the entity is in. /// /// This can be used to check if the entity is in the same world as another /// entity. /// - /// Also see [`Client::instance_name`], - #[doc(alias("world_name", "dimension_name"))] - pub fn instance_name(&self) -> InstanceName { - (*self.component::<InstanceName>()).clone() + /// Also see [`Client::world_name`], + #[doc(alias("dimension_name"))] + pub fn world_name(&self) -> WorldName { + (*self.component::<WorldName>()).clone() } Client: diff --git a/azalea/src/events.rs b/azalea/src/events.rs index 18d24773..b0bc8cd1 100644 --- a/azalea/src/events.rs +++ b/azalea/src/events.rs @@ -7,7 +7,7 @@ use azalea_chat::FormattedText; use azalea_core::{entity_id::MinecraftEntityId, position::ChunkPos, tick::GameTick}; use azalea_entity::{Dead, InLoadedChunk}; use azalea_protocol::packets::game::c_player_combat_kill::ClientboundPlayerCombatKill; -use azalea_world::InstanceName; +use azalea_world::WorldName; use bevy_app::{App, Plugin, PreUpdate, Update}; use bevy_ecs::prelude::*; use derive_more::{Deref, DerefMut}; @@ -211,7 +211,7 @@ pub fn chat_listener( } // only tick if we're in a world -pub fn tick_listener(query: Query<&LocalPlayerEvents, With<InstanceName>>) { +pub fn tick_listener(query: Query<&LocalPlayerEvents, With<WorldName>>) { for local_player_events in &query { let _ = local_player_events.send(Event::Tick); } diff --git a/azalea/src/nearest_entity.rs b/azalea/src/nearest_entity.rs index bf3f2fdb..3dc32adc 100644 --- a/azalea/src/nearest_entity.rs +++ b/azalea/src/nearest_entity.rs @@ -1,6 +1,6 @@ use azalea_core::entity_id::MinecraftEntityId; use azalea_entity::Position; -use azalea_world::InstanceName; +use azalea_world::WorldName; use bevy_ecs::{ prelude::Entity, query::{QueryFilter, With}, @@ -11,8 +11,8 @@ use bevy_ecs::{ /// entity, (or several) close to a given position. /// /// This system parameter allows for additional filtering of entities based off -/// of ECS marker components, such as `With<>`, `Without<>`, or `Added<>`, etc. -/// All functions used by this system parameter instance will respect the +/// of ECS marker components, such as `With<T>`, `Without<T>`, or `Added<T>`, +/// etc. All functions used by this system parameter instance will respect the /// applied filter. /// /// ``` @@ -50,13 +50,12 @@ pub struct EntityFinder<'w, 's, F = ()> where F: QueryFilter + 'static, { - all_entities: - Query<'w, 's, (&'static Position, &'static InstanceName), With<MinecraftEntityId>>, + all_entities: Query<'w, 's, (&'static Position, &'static WorldName), With<MinecraftEntityId>>, filtered_entities: Query< 'w, 's, - (Entity, &'static InstanceName, &'static Position), + (Entity, &'static WorldName, &'static Position), (With<MinecraftEntityId>, F), >, } @@ -65,21 +64,22 @@ impl<'a, F> EntityFinder<'_, '_, F> where F: QueryFilter + 'static, { - /// Gets the nearest entity to the given position and world instance name. + /// Gets the nearest entity to the given position and with the given world + /// name. /// /// This method will return `None` if there are no entities within range. If /// multiple entities are within range, only the closest one is returned. pub fn nearest_to_position( &'a self, position: Position, - instance_name: &InstanceName, + world_name: &WorldName, max_distance: f64, ) -> Option<Entity> { let mut nearest_entity = None; let mut min_distance = max_distance; - for (target_entity, e_instance, e_pos) in self.filtered_entities.iter() { - if e_instance != instance_name { + for (target_entity, e_world, e_pos) in self.filtered_entities.iter() { + if e_world != world_name { continue; } @@ -99,19 +99,19 @@ where /// multiple entities are within range, only the closest one is /// returned. pub fn nearest_to_entity(&'a self, entity: Entity, max_distance: f64) -> Option<Entity> { - let Ok((position, instance_name)) = self.all_entities.get(entity) else { + let Ok((position, world_name)) = self.all_entities.get(entity) else { return None; }; let mut nearest_entity = None; let mut min_distance = max_distance; - for (target_entity, e_instance, e_pos) in self.filtered_entities.iter() { + for (target_entity, e_world, e_pos) in self.filtered_entities.iter() { if entity == target_entity { continue; }; - if e_instance != instance_name { + if e_world != world_name { continue; } @@ -135,13 +135,13 @@ where pub fn nearby_entities_to_position( &'a self, position: &'a Position, - instance_name: &'a InstanceName, + world_name: &'a WorldName, max_distance: f64, ) -> impl Iterator<Item = (Entity, f64)> + 'a { self.filtered_entities .iter() - .filter_map(move |(target_entity, e_instance, e_pos)| { - if e_instance != instance_name { + .filter_map(move |(target_entity, e_world, e_pos)| { + if e_world != world_name { return None; } @@ -167,23 +167,23 @@ where max_distance: f64, ) -> impl Iterator<Item = (Entity, f64)> + 'a { let position; - let instance_name; - if let Ok((pos, instance)) = self.all_entities.get(entity) { - position = *pos; - instance_name = Some(instance); + let world_name; + if let Ok((p, w)) = self.all_entities.get(entity) { + position = *p; + world_name = Some(w); } else { position = Position::default(); - instance_name = None; + world_name = None; }; self.filtered_entities .iter() - .filter_map(move |(target_entity, e_instance, e_pos)| { + .filter_map(move |(target_entity, e_world, e_pos)| { if entity == target_entity { return None; } - if Some(e_instance) != instance_name { + if Some(e_world) != world_name { return None; } diff --git a/azalea/src/pathfinder/debug.rs b/azalea/src/pathfinder/debug.rs index 25f82946..7fe44919 100644 --- a/azalea/src/pathfinder/debug.rs +++ b/azalea/src/pathfinder/debug.rs @@ -1,4 +1,4 @@ -use azalea_client::{chat::SendChatEvent, local_player::InstanceHolder}; +use azalea_client::{chat::SendChatEvent, local_player::WorldHolder}; use azalea_core::position::Vec3; use bevy_ecs::prelude::*; @@ -35,7 +35,7 @@ use super::ExecutingPath; pub struct PathfinderDebugParticles; pub fn debug_render_path_with_particles( - mut query: Query<(Entity, &ExecutingPath, &InstanceHolder), With<PathfinderDebugParticles>>, + mut query: Query<(Entity, &ExecutingPath, &WorldHolder), With<PathfinderDebugParticles>>, // chat_events is Option because the tests don't have SendChatEvent // and we have to use ResMut<Messages> because bevy doesn't support Option<MessageWriter> chat_events: Option<ResMut<Messages<SendChatEvent>>>, @@ -50,12 +50,12 @@ pub fn debug_render_path_with_particles( *tick_count += 1; return; } - for (entity, executing_path, instance_holder) in &mut query { + for (entity, executing_path, world_holder) in &mut query { if executing_path.path.is_empty() { continue; } - let chunks = &instance_holder.instance.read().chunks; + let chunks = &world_holder.shared.read().chunks; let mut start = executing_path.last_reached_node; for (i, edge) in executing_path.path.iter().enumerate() { diff --git a/azalea/src/pathfinder/extras/utils.rs b/azalea/src/pathfinder/extras/utils.rs index 3ae0b457..53345139 100644 --- a/azalea/src/pathfinder/extras/utils.rs +++ b/azalea/src/pathfinder/extras/utils.rs @@ -115,13 +115,13 @@ pub fn get_hit_result_while_looking_at_with_eye_position( #[cfg(test)] mod tests { use azalea_core::position::ChunkPos; - use azalea_world::{Chunk, PartialInstance}; + use azalea_world::{Chunk, PartialWorld}; use super::*; #[test] fn test_cannot_reach_block_through_wall_when_y_is_negative() { - let mut partial_world = PartialInstance::default(); + let mut partial_world = PartialWorld::default(); let mut world = ChunkStorage::default(); partial_world .chunks diff --git a/azalea/src/pathfinder/mod.rs b/azalea/src/pathfinder/mod.rs index fe94e42d..96de98da 100644 --- a/azalea/src/pathfinder/mod.rs +++ b/azalea/src/pathfinder/mod.rs @@ -36,7 +36,7 @@ use azalea_block::{BlockState, BlockTrait}; use azalea_client::{ StartSprintEvent, StartWalkEvent, inventory::InventorySystems, - local_player::InstanceHolder, + local_player::WorldHolder, mining::{Mining, MiningSystems, StartMiningBlockEvent}, movement::MoveEventsSystems, }; @@ -46,7 +46,7 @@ use azalea_core::{ }; use azalea_entity::{LocalEntity, Physics, Position, inventory::Inventory, metadata::Player}; use azalea_physics::{PhysicsSystems, get_block_pos_below_that_affects_movement}; -use azalea_world::{InstanceContainer, InstanceName}; +use azalea_world::{WorldName, Worlds}; use bevy_app::{PreUpdate, Update}; use bevy_ecs::prelude::*; use bevy_tasks::{AsyncComputeTaskPool, Task}; @@ -109,7 +109,7 @@ impl Plugin for PathfinderPlugin { ( goto_listener, handle_tasks, - stop_pathfinding_on_instance_change, + stop_pathfinding_on_world_change, path_found_listener, handle_stop_pathfinding_event, ) @@ -307,16 +307,16 @@ pub fn goto_listener( &mut Pathfinder, Option<&mut ExecutingPath>, &Position, - &InstanceName, + &WorldName, &Inventory, Option<&CustomPathfinderState>, )>, - instance_container: Res<InstanceContainer>, + worlds: Res<Worlds>, ) { let thread_pool = AsyncComputeTaskPool::get(); for event in events.read() { - let Ok((mut pathfinder, executing_path, position, instance_name, inventory, custom_state)) = + let Ok((mut pathfinder, executing_path, position, world_name, inventory, custom_state)) = query.get_mut(event.entity) else { warn!("got goto event for an entity that can't pathfind"); @@ -367,8 +367,8 @@ pub fn goto_listener( ); } - let world_lock = instance_container - .get(instance_name) + let world_lock = worlds + .get(world_name) .expect("Entity tried to pathfind but the entity isn't in a valid world"); let goal = event.goal.clone(); @@ -417,7 +417,7 @@ pub struct CalculatePathCtx { pub entity: Entity, pub start: BlockPos, pub goal: Arc<dyn Goal>, - pub world_lock: Arc<RwLock<azalea_world::Instance>>, + pub world_lock: Arc<RwLock<azalea_world::World>>, pub goto_id_atomic: Arc<AtomicUsize>, pub mining_cache: MiningCache, pub custom_state: CustomPathfinderState, @@ -559,15 +559,15 @@ pub fn path_found_listener( mut query: Query<( &mut Pathfinder, Option<&mut ExecutingPath>, - &InstanceName, + &WorldName, &Inventory, Option<&CustomPathfinderState>, )>, - instance_container: Res<InstanceContainer>, + worlds: Res<Worlds>, mut commands: Commands, ) { for event in events.read() { - let Ok((mut pathfinder, executing_path, instance_name, inventory, custom_state)) = + let Ok((mut pathfinder, executing_path, world_name, inventory, custom_state)) = query.get_mut(event.entity) else { debug!("got path found event for an entity that can't pathfind"); @@ -580,8 +580,8 @@ pub fn path_found_listener( // combine the old and new paths if the first node of the new path is a // successor of the last node of the old path if let Some(last_node_of_current_path) = executing_path.path.back() { - let world_lock = instance_container - .get(instance_name) + let world_lock = worlds + .get(world_name) .expect("Entity tried to pathfind but the entity isn't in a valid world"); let origin = event.start; let successors_fn: moves::SuccessorsFn = event.successors_fn; @@ -676,11 +676,11 @@ pub fn timeout_movement( &mut ExecutingPath, &Position, Option<&Mining>, - &InstanceName, + &WorldName, &Inventory, Option<&CustomPathfinderState>, )>, - instance_container: Res<InstanceContainer>, + worlds: Res<Worlds>, ) { for ( entity, @@ -688,7 +688,7 @@ pub fn timeout_movement( mut executing_path, position, mining, - instance_name, + world_name, inventory, custom_state, ) in &mut query @@ -713,8 +713,8 @@ pub fn timeout_movement( let cur_pos = player_pos_to_block_pos(**position); executing_path.last_reached_node = cur_pos; - let world_lock = instance_container - .get(instance_name) + let world_lock = worlds + .get(world_name) .expect("Entity tried to pathfind but the entity isn't in a valid world"); let Some(opts) = pathfinder.opts.clone() else { warn!( @@ -751,15 +751,14 @@ pub fn check_node_reached( &mut ExecutingPath, &Position, &Physics, - &InstanceName, + &WorldName, )>, mut walk_events: MessageWriter<StartWalkEvent>, mut commands: Commands, - instance_container: Res<InstanceContainer>, + worlds: Res<Worlds>, ) { - for (entity, mut pathfinder, mut executing_path, position, physics, instance_name) in &mut query - { - let Some(instance) = instance_container.get(instance_name) else { + for (entity, mut pathfinder, mut executing_path, position, physics, world_name) in &mut query { + let Some(world) = worlds.get(world_name) else { warn!("entity is pathfinding but not in a valid world"); continue; }; @@ -794,8 +793,8 @@ pub fn check_node_reached( let block_pos_below = get_block_pos_below_that_affects_movement(*position); let block_state_below = { - let instance = instance.read(); - instance + let world = world.read(); + world .chunks .get_block_state(block_pos_below) .unwrap_or(BlockState::AIR) @@ -879,21 +878,21 @@ pub fn check_for_path_obstruction( Entity, &mut Pathfinder, &mut ExecutingPath, - &InstanceName, + &WorldName, &Inventory, Option<&CustomPathfinderState>, )>, - instance_container: Res<InstanceContainer>, + worlds: Res<Worlds>, ) { - for (entity, mut pathfinder, mut executing_path, instance_name, inventory, custom_state) in + for (entity, mut pathfinder, mut executing_path, world_name, inventory, custom_state) in &mut query { let Some(opts) = pathfinder.opts.clone() else { continue; }; - let world_lock = instance_container - .get(instance_name) + let world_lock = worlds + .get(world_name) .expect("Entity tried to pathfind but the entity isn't in a valid world"); // obstruction check (the path we're executing isn't possible anymore) @@ -948,8 +947,8 @@ pub fn check_for_path_obstruction( continue; }; - let world_lock = instance_container - .get(instance_name) + let world_lock = worlds + .get(world_name) .expect("Entity tried to pathfind but the entity isn't in a valid world"); // patch up to 20 nodes @@ -980,7 +979,7 @@ fn patch_path( pathfinder: &mut Pathfinder, inventory: &Inventory, entity: Entity, - world_lock: Arc<RwLock<azalea_world::Instance>>, + world_lock: Arc<RwLock<azalea_world::World>>, custom_state: CustomPathfinderState, opts: PathfinderOpts, ) { @@ -1145,7 +1144,7 @@ pub fn tick_execute_path( &Position, &Physics, Option<&Mining>, - &InstanceHolder, + &WorldHolder, &Inventory, )>, mut look_at_events: MessageWriter<LookAtEvent>, @@ -1154,7 +1153,7 @@ pub fn tick_execute_path( mut jump_events: MessageWriter<JumpEvent>, mut start_mining_events: MessageWriter<StartMiningBlockEvent>, ) { - for (entity, executing_path, position, physics, mining, instance_holder, inventory_component) in + for (entity, executing_path, position, physics, mining, world_holder, inventory_component) in &mut query { if let Some(edge) = executing_path.path.front() { @@ -1165,7 +1164,7 @@ pub fn tick_execute_path( start: executing_path.last_reached_node, physics, is_currently_mining: mining.is_some(), - instance: instance_holder.instance.clone(), + world: world_holder.shared.clone(), menu: inventory_component.inventory_menu.clone(), commands: &mut commands, @@ -1246,13 +1245,13 @@ pub fn handle_stop_pathfinding_event( } } -pub fn stop_pathfinding_on_instance_change( - mut query: Query<(Entity, &mut ExecutingPath), Changed<InstanceName>>, +pub fn stop_pathfinding_on_world_change( + mut query: Query<(Entity, &mut ExecutingPath), Changed<WorldName>>, mut stop_pathfinding_events: MessageWriter<StopPathfindingEvent>, ) { for (entity, mut executing_path) in &mut query { if !executing_path.path.is_empty() { - debug!("instance changed, clearing path"); + debug!("world changed, clearing path"); executing_path.path.clear(); stop_pathfinding_events.write(StopPathfindingEvent { entity, diff --git a/azalea/src/pathfinder/moves/mod.rs b/azalea/src/pathfinder/moves/mod.rs index 33c34c3b..d575c01a 100644 --- a/azalea/src/pathfinder/moves/mod.rs +++ b/azalea/src/pathfinder/moves/mod.rs @@ -13,7 +13,7 @@ use azalea_client::{ }; use azalea_core::position::{BlockPos, Vec3}; use azalea_inventory::Menu; -use azalea_world::Instance; +use azalea_world::World; use bevy_ecs::{entity::Entity, message::MessageWriter, system::Commands}; use parking_lot::RwLock; use tracing::debug; @@ -65,7 +65,7 @@ pub struct ExecuteCtx<'s, 'w1, 'w2, 'w3, 'w4, 'w5, 'w6, 'a> { pub position: Vec3, pub physics: &'a azalea_entity::Physics, pub is_currently_mining: bool, - pub instance: Arc<RwLock<Instance>>, + pub world: Arc<RwLock<World>>, pub menu: Menu, pub commands: &'a mut Commands<'w1, 's>, @@ -124,11 +124,7 @@ impl ExecuteCtx<'_, '_, '_, '_, '_, '_, '_, '_> { /// Returns whether this block could be mined. pub fn should_mine(&mut self, block: BlockPos) -> bool { - let block_state = self - .instance - .read() - .get_block_state(block) - .unwrap_or_default(); + let block_state = self.world.read().get_block_state(block).unwrap_or_default(); if is_block_state_passable(block_state) { // block is already passable, no need to mine it return false; @@ -141,11 +137,7 @@ impl ExecuteCtx<'_, '_, '_, '_, '_, '_, '_, '_> { /// /// Returns whether the block is being mined. pub fn mine(&mut self, block: BlockPos) -> bool { - let block_state = self - .instance - .read() - .get_block_state(block) - .unwrap_or_default(); + let block_state = self.world.read().get_block_state(block).unwrap_or_default(); if is_block_state_passable(block_state) { // block is already passable, no need to mine it return false; @@ -196,10 +188,7 @@ impl ExecuteCtx<'_, '_, '_, '_, '_, '_, '_, '_> { } pub fn get_block_state(&self, block: BlockPos) -> BlockState { - self.instance - .read() - .get_block_state(block) - .unwrap_or_default() + self.world.read().get_block_state(block).unwrap_or_default() } } diff --git a/azalea/src/pathfinder/simulation.rs b/azalea/src/pathfinder/simulation.rs index ca5e4f36..94837f9e 100644 --- a/azalea/src/pathfinder/simulation.rs +++ b/azalea/src/pathfinder/simulation.rs @@ -13,8 +13,8 @@ use azalea_entity::{ Attributes, LookDirection, Physics, Position, dimensions::EntityDimensions, inventory::Inventory, }; -use azalea_registry::{builtin::EntityKind, identifier::Identifier}; -use azalea_world::{ChunkStorage, Instance, InstanceContainer, PartialInstance}; +use azalea_registry::builtin::EntityKind; +use azalea_world::{ChunkStorage, PartialWorld, World, WorldName, Worlds}; use bevy_app::App; use bevy_ecs::prelude::*; use parking_lot::RwLock; @@ -45,14 +45,14 @@ impl SimulatedPlayerBundle { } } -fn simulation_instance_name() -> Identifier { - Identifier::new("azalea:simulation") +fn simulation_world_name() -> WorldName { + WorldName::new("azalea:simulation") } -fn create_simulation_instance(chunks: ChunkStorage) -> (App, Arc<RwLock<Instance>>) { - let instance_name = simulation_instance_name(); +fn create_simulation_world(chunks: ChunkStorage) -> (App, Arc<RwLock<World>>) { + let world_name = simulation_world_name(); - let instance = Arc::new(RwLock::new(Instance { + let world = Arc::new(RwLock::new(World { chunks, ..Default::default() })); @@ -72,8 +72,8 @@ fn create_simulation_instance(chunks: ChunkStorage) -> (App, Arc<RwLock<Instance azalea_client::interact::InteractPlugin, azalea_client::loading::PlayerLoadedPlugin, )) - .insert_resource(InstanceContainer { - instances: [(instance_name.clone(), Arc::downgrade(&instance.clone()))] + .insert_resource(Worlds { + map: [(world_name.clone(), Arc::downgrade(&world.clone()))] .iter() .cloned() .collect(), @@ -83,14 +83,14 @@ fn create_simulation_instance(chunks: ChunkStorage) -> (App, Arc<RwLock<Instance schedule.set_executor_kind(bevy_ecs::schedule::ExecutorKind::SingleThreaded); }); - (app, instance) + (app, world) } fn create_simulation_player_complete_bundle( - instance: Arc<RwLock<Instance>>, + world: Arc<RwLock<World>>, player: &SimulatedPlayerBundle, ) -> impl Bundle { - let instance_name = simulation_instance_name(); + let world_name = simulation_world_name(); ( MinecraftEntityId(0), @@ -100,12 +100,12 @@ fn create_simulation_player_complete_bundle( Uuid::nil(), *player.position, EntityKind::Player, - instance_name, + world_name, ), - azalea_client::local_player::InstanceHolder { - // partial_instance is never actually used by the pathfinder so - partial_instance: Arc::new(RwLock::new(PartialInstance::default())), - instance: instance.clone(), + azalea_client::local_player::WorldHolder { + // the partial world is never actually used by the pathfinder, so we can leave it empty + partial: Arc::new(RwLock::new(PartialWorld::default())), + shared: world.clone(), }, Inventory::default(), LocalGameMode::from(GameMode::Survival), @@ -117,11 +117,11 @@ fn create_simulation_player_complete_bundle( } fn create_simulation_player( - ecs: &mut World, - instance: Arc<RwLock<Instance>>, + ecs: &mut bevy_ecs::world::World, + world: Arc<RwLock<World>>, player: SimulatedPlayerBundle, ) -> Entity { - let mut entity = ecs.spawn(create_simulation_player_complete_bundle(instance, &player)); + let mut entity = ecs.spawn(create_simulation_player_complete_bundle(world, &player)); entity.insert(player); entity.id() } @@ -130,17 +130,17 @@ fn create_simulation_player( pub struct Simulation { pub app: App, pub entity: Entity, - _instance: Arc<RwLock<Instance>>, + _world: Arc<RwLock<World>>, } impl Simulation { pub fn new(chunks: ChunkStorage, player: SimulatedPlayerBundle) -> Self { - let (mut app, instance) = create_simulation_instance(chunks); - let entity = create_simulation_player(app.world_mut(), instance.clone(), player); + let (mut app, world) = create_simulation_world(chunks); + let entity = create_simulation_player(app.world_mut(), world.clone(), player); Self { app, entity, - _instance: instance, + _world: world, } } @@ -168,12 +168,12 @@ impl Simulation { /// A set of simulations, useful for efficiently doing multiple simulations. pub struct SimulationSet { pub app: App, - instance: Arc<RwLock<Instance>>, + world: Arc<RwLock<World>>, } impl SimulationSet { pub fn new(chunks: ChunkStorage) -> Self { - let (app, instance) = create_simulation_instance(chunks); - Self { app, instance } + let (app, world) = create_simulation_world(chunks); + Self { app, world } } pub fn tick(&mut self) { self.app.update(); @@ -181,7 +181,7 @@ impl SimulationSet { } pub fn spawn(&mut self, player: SimulatedPlayerBundle) -> Entity { - create_simulation_player(self.app.world_mut(), self.instance.clone(), player) + create_simulation_player(self.app.world_mut(), self.world.clone(), player) } pub fn despawn(&mut self, entity: Entity) { self.app.world_mut().despawn(entity); diff --git a/azalea/src/pathfinder/world.rs b/azalea/src/pathfinder/world.rs index 13d60162..fdeb0b2f 100644 --- a/azalea/src/pathfinder/world.rs +++ b/azalea/src/pathfinder/world.rs @@ -11,7 +11,7 @@ use azalea_core::{ }; use azalea_physics::collision::BlockWithShape; use azalea_registry::{builtin::BlockKind, tags}; -use azalea_world::{Instance, palette::PalettedContainer}; +use azalea_world::{World, palette::PalettedContainer}; use parking_lot::RwLock; use super::{mining::MiningCache, rel_block_pos::RelBlockPos}; @@ -25,7 +25,7 @@ pub struct CachedWorld { origin: BlockPos, min_y: i32, - world_lock: Arc<RwLock<Instance>>, + world_lock: Arc<RwLock<World>>, // we store `PalettedContainer`s instead of `Chunk`s or `Section`s because it doesn't contain // any unnecessary data like heightmaps or biomes. @@ -99,7 +99,7 @@ pub struct CachedSection { } impl CachedWorld { - pub fn new(world_lock: Arc<RwLock<Instance>>, origin: BlockPos) -> Self { + pub fn new(world_lock: Arc<RwLock<World>>, origin: BlockPos) -> Self { let min_y = world_lock.read().chunks.min_y; Self { origin, @@ -675,13 +675,13 @@ pub fn is_block_state_water(block_state: BlockState) -> bool { #[cfg(test)] mod tests { - use azalea_world::{Chunk, ChunkStorage, PartialInstance}; + use azalea_world::{Chunk, ChunkStorage, PartialWorld}; use super::*; #[test] fn test_is_passable() { - let mut partial_world = PartialInstance::default(); + let mut partial_world = PartialWorld::default(); let mut world = ChunkStorage::default(); partial_world @@ -703,7 +703,7 @@ mod tests { #[test] fn test_is_solid() { - let mut partial_world = PartialInstance::default(); + let mut partial_world = PartialWorld::default(); let mut world = ChunkStorage::default(); partial_world .chunks @@ -724,7 +724,7 @@ mod tests { #[test] fn test_is_standable() { - let mut partial_world = PartialInstance::default(); + let mut partial_world = PartialWorld::default(); let mut world = ChunkStorage::default(); partial_world .chunks diff --git a/azalea/src/swarm/builder.rs b/azalea/src/swarm/builder.rs index 14c9c290..560be3d8 100644 --- a/azalea/src/swarm/builder.rs +++ b/azalea/src/swarm/builder.rs @@ -10,7 +10,7 @@ use std::{ use azalea_client::{DefaultPlugins, account::Account, start_ecs_runner}; use azalea_protocol::address::{ResolvableAddr, ResolvedAddr}; -use azalea_world::InstanceContainer; +use azalea_world::Worlds; use bevy_app::{App, AppExit, Plugins, SubApp}; use bevy_ecs::{component::Component, resource::Resource}; use futures::future::join_all; @@ -431,7 +431,7 @@ where addr }; - let instance_container = Arc::new(RwLock::new(InstanceContainer::default())); + let worlds = Arc::new(RwLock::new(Worlds::default())); // we can't modify the swarm plugins after this let (bots_tx, mut bots_rx) = mpsc::unbounded_channel(); @@ -451,7 +451,7 @@ where ecs: ecs_lock.clone(), address: Arc::new(RwLock::new(address)), - instance_container, + worlds, bots_tx, diff --git a/azalea/src/swarm/chat.rs b/azalea/src/swarm/chat.rs index 0bad69c1..c5e3eba3 100644 --- a/azalea/src/swarm/chat.rs +++ b/azalea/src/swarm/chat.rs @@ -2,12 +2,12 @@ // How the chat event works (to avoid firing the event multiple times): // --- -// There's a shared queue of all the chat messages -// Each bot contains an index of the farthest message we've seen -// When a bot receives a chat messages, it looks into the queue to find the -// earliest instance of the message content that's after the bot's chat index. -// If it finds it, then its personal index is simply updated. Otherwise, fire -// the event and add to the queue. +// There's a shared queue of all the chat messages. Each bot contains an index +// of the farthest message that it has seen. When a bot receives a chat +// message, it looks into the shared queue to find the earliest instance of the +// message content, that's after the bot's current chat index. If it finds it, +// then its personal index is simply updated. Otherwise, it fires the event and +// adds to the shared queue. // // To make sure the queue doesn't grow too large, we keep a `chat_min_index` // in Swarm that's set to the smallest index of all the bots, and we remove all diff --git a/azalea/src/swarm/events.rs b/azalea/src/swarm/events.rs index ee5859ca..83817c86 100644 --- a/azalea/src/swarm/events.rs +++ b/azalea/src/swarm/events.rs @@ -1,4 +1,4 @@ -use azalea_client::local_player::InstanceHolder; +use azalea_client::local_player::WorldHolder; use azalea_core::entity_id::MinecraftEntityId; use bevy_app::{App, Plugin, Update}; use bevy_ecs::prelude::*; @@ -21,7 +21,7 @@ pub struct SwarmReadyEvent; struct IsSwarmReady(bool); fn check_ready( - query: Query<Option<&MinecraftEntityId>, With<InstanceHolder>>, + query: Query<Option<&MinecraftEntityId>, With<WorldHolder>>, mut is_swarm_ready: ResMut<IsSwarmReady>, mut ready_events: MessageWriter<SwarmReadyEvent>, ) { diff --git a/azalea/src/swarm/mod.rs b/azalea/src/swarm/mod.rs index b1061346..4ecb0726 100644 --- a/azalea/src/swarm/mod.rs +++ b/azalea/src/swarm/mod.rs @@ -15,7 +15,7 @@ use std::sync::{ use azalea_client::{account::Account, chat::ChatPacket, join::ConnectOpts}; use azalea_entity::LocalEntity; use azalea_protocol::address::ResolvedAddr; -use azalea_world::InstanceContainer; +use azalea_world::Worlds; use bevy_app::{PluginGroup, PluginGroupBuilder}; use bevy_ecs::prelude::*; pub use builder::SwarmBuilder; @@ -47,7 +47,7 @@ pub struct Swarm { // the address is public and mutable so plugins can change it pub address: Arc<RwLock<ResolvedAddr>>, - pub instance_container: Arc<RwLock<InstanceContainer>>, + pub worlds: Arc<RwLock<Worlds>>, /// This is used internally to make the client handler function work. pub(crate) bots_tx: mpsc::UnboundedSender<(Option<crate::Event>, Client)>, |
