diff --git a/azalea-client/src/client.rs b/azalea-client/src/client.rs index 8f460da8..47cc7235 100644 --- a/azalea-client/src/client.rs +++ b/azalea-client/src/client.rs @@ -38,7 +38,7 @@ use azalea_protocol::{ }; use azalea_world::{ entity::{EntityPlugin, EntityUpdateSet, Local, WorldName}, - Instance, PartialWorld, WorldContainer, + Instance, InstanceContainer, PartialInstance, }; use bevy_app::{App, CoreSchedule, Plugin, PluginGroup, PluginGroupBuilder}; use bevy_ecs::{ @@ -75,13 +75,13 @@ pub struct Client { /// and skin data. /// /// This is immutable; the server cannot change it. To get the username and - /// skin the server chose for you, get your player from - /// [`Self::players`]. + /// skin the server chose for you, get your player from the [`TabList`] + /// component. pub profile: GameProfile, /// The entity for this client in the ECS. pub entity: Entity, /// The world that this client is in. - pub world: Arc>, + pub world: Arc>, /// The entity component system. You probably don't need to access this /// directly. Note that if you're using a shared world (i.e. a swarm), this @@ -94,8 +94,7 @@ pub struct Client { /// A component that contains some of the "settings" for this client that are /// sent to the server, such as render distance. -#[derive(Component, Clone, Debug, Deref, DerefMut, Default, Eq, PartialEq)] -pub struct ClientInformation(ServerboundClientInformationPacket); +pub type ClientInformation = ServerboundClientInformationPacket; /// A component that contains a map of player UUIDs to their information in the /// tab list @@ -137,7 +136,7 @@ impl Client { profile, // default our id to 0, it'll be set later entity, - world: Arc::new(RwLock::new(PartialWorld::default())), + world: Arc::new(RwLock::new(PartialInstance::default())), ecs, @@ -424,14 +423,14 @@ impl Client { /// Get a reference to our (potentially shared) world. /// - /// This gets the [`World`] from our world container. If it's a normal + /// This gets the [`Instance`] from our world container. If it's a normal /// client, then it'll be the same as the world the client has loaded. /// If the client using a shared world, then the shared world will be a /// superset of the client's world. pub fn world(&self) -> Arc> { let world_name = self.component::(); let ecs = self.ecs.lock(); - let world_container = ecs.resource::(); + let world_container = ecs.resource::(); world_container.get(&world_name).unwrap() } @@ -464,7 +463,7 @@ impl Client { { let mut ecs = self.ecs.lock(); let mut client_information_mut = self.query::<&mut ClientInformation>(&mut ecs); - **client_information_mut = client_information.clone(); + *client_information_mut = client_information.clone(); } if self.logged_in() { @@ -514,7 +513,7 @@ impl Plugin for AzaleaPlugin { app.add_event::() .add_system(handle_send_packet_event); - app.init_resource::(); + app.init_resource::(); } } diff --git a/azalea-client/src/lib.rs b/azalea-client/src/lib.rs index 44a4db6b..8c3936cd 100644 --- a/azalea-client/src/lib.rs +++ b/azalea-client/src/lib.rs @@ -26,7 +26,9 @@ mod player; pub mod task_pool; pub use account::Account; -pub use client::{init_ecs_app, start_ecs, Client, ClientInformation, JoinError}; +pub use client::{ + init_ecs_app, start_ecs, Client, ClientInformation, JoinError, JoinedClientBundle, TabList, +}; pub use events::Event; pub use local_player::{GameProfileComponent, LocalPlayer}; pub use movement::{SprintDirection, StartSprintEvent, StartWalkEvent, WalkDirection}; diff --git a/azalea-client/src/local_player.rs b/azalea-client/src/local_player.rs index 7ec3d0dc..540ef3b4 100644 --- a/azalea-client/src/local_player.rs +++ b/azalea-client/src/local_player.rs @@ -5,7 +5,7 @@ use azalea_core::ChunkPos; use azalea_protocol::packets::game::ServerboundGamePacket; use azalea_world::{ entity::{self, Dead}, - Instance, PartialWorld, + Instance, PartialInstance, }; use bevy_ecs::{ component::Component, entity::Entity, event::EventReader, query::Added, system::Query, @@ -33,11 +33,12 @@ use crate::{ pub struct LocalPlayer { packet_writer: mpsc::UnboundedSender, - /// The partial world is the world this client currently has loaded. It has - /// a limited render distance. - pub partial_world: Arc>, - /// The world is the combined [`PartialWorld`]s of all clients in the same - /// world. (Only relevant if you're using a shared world, i.e. a swarm) + /// The partial instance is the world this client currently has loaded. It + /// has a limited render distance. + pub partial_instance: Arc>, + /// The world is the combined [`PartialInstance`]s of all clients in the + /// same world. (Only relevant if you're using a shared world, i.e. a + /// swarm) pub world: Arc>, /// A task that reads packets from the server. The client is disconnected @@ -92,7 +93,7 @@ impl LocalPlayer { packet_writer, world, - partial_world: Arc::new(RwLock::new(PartialWorld::new( + partial_instance: Arc::new(RwLock::new(PartialInstance::new( client_information.view_distance.into(), Some(entity), ))), diff --git a/azalea-client/src/packet_handling.rs b/azalea-client/src/packet_handling.rs index ae38ec5a..a75f2760 100644 --- a/azalea-client/src/packet_handling.rs +++ b/azalea-client/src/packet_handling.rs @@ -20,7 +20,7 @@ use azalea_world::{ MinecraftEntityId, Physics, PlayerBundle, Position, WorldName, }, entity::{LoadedBy, RelativeEntityUpdate}, - PartialWorld, WorldContainer, + InstanceContainer, PartialInstance, }; use bevy_app::{App, CoreSet, Plugin}; use bevy_ecs::{ @@ -192,7 +192,7 @@ fn process_packet_events(ecs: &mut World) { &GameProfileComponent, &ClientInformation, )>, - ResMut, + ResMut, )> = SystemState::new(ecs); let (mut commands, mut query, mut world_container) = system_state.get_mut(ecs); let (mut local_player, world_name, game_profile, client_information) = @@ -231,7 +231,7 @@ fn process_packet_events(ecs: &mut World) { // (when we add chunks or entities those will be in the // world_container) - *local_player.partial_world.write() = PartialWorld::new( + *local_player.partial_instance.write() = PartialInstance::new( client_information.view_distance.into(), // this argument makes it so other clients don't update this // player entity @@ -260,8 +260,7 @@ fn process_packet_events(ecs: &mut World) { "Sending client information because login: {:?}", client_information ); - let client_information: ClientInformation = client_information.clone(); - local_player.write_packet((*client_information).clone().get()); + local_player.write_packet(client_information.clone().get()); // brand local_player.write_packet( @@ -478,7 +477,7 @@ fn process_packet_events(ecs: &mut World) { let mut system_state: SystemState> = SystemState::new(ecs); let mut query = system_state.get_mut(ecs); let local_player = query.get_mut(player_entity).unwrap(); - let mut partial_world = local_player.partial_world.write(); + let mut partial_world = local_player.partial_instance.write(); partial_world.chunks.view_center = ChunkPos::new(p.x, p.z); } @@ -497,14 +496,14 @@ fn process_packet_events(ecs: &mut World) { // by this client. let shared_chunk = local_player.world.read().chunks.get(&pos); let this_client_has_chunk = local_player - .partial_world + .partial_instance .read() .chunks .limited_get(&pos) .is_some(); let mut world = local_player.world.write(); - let mut partial_world = local_player.partial_world.write(); + let mut partial_world = local_player.partial_instance.write(); if !this_client_has_chunk { if let Some(shared_chunk) = shared_chunk { @@ -673,7 +672,7 @@ fn process_packet_events(ecs: &mut World) { if let Some(entity) = entity { let new_position = p.position; commands.entity(entity).add(RelativeEntityUpdate { - partial_world: local_player.partial_world.clone(), + partial_world: local_player.partial_instance.clone(), update: Box::new(move |entity| { let mut position = entity.get_mut::().unwrap(); **position = new_position; @@ -704,7 +703,7 @@ fn process_packet_events(ecs: &mut World) { if let Some(entity) = entity { let delta = p.delta.clone(); commands.entity(entity).add(RelativeEntityUpdate { - partial_world: local_player.partial_world.clone(), + partial_world: local_player.partial_instance.clone(), update: Box::new(move |entity_mut| { let mut position = entity_mut.get_mut::().unwrap(); **position = position.with_delta(&delta); @@ -732,7 +731,7 @@ fn process_packet_events(ecs: &mut World) { if let Some(entity) = entity { let delta = p.delta.clone(); commands.entity(entity).add(RelativeEntityUpdate { - partial_world: local_player.partial_world.clone(), + partial_world: local_player.partial_instance.clone(), update: Box::new(move |entity_mut| { let mut position = entity_mut.get_mut::().unwrap(); **position = position.with_delta(&delta); diff --git a/azalea-physics/src/lib.rs b/azalea-physics/src/lib.rs index 1736b8fb..5331e02d 100644 --- a/azalea-physics/src/lib.rs +++ b/azalea-physics/src/lib.rs @@ -10,7 +10,7 @@ use azalea_world::{ metadata::Sprinting, move_relative, Attributes, Jumping, Local, Physics, Position, WorldName, }, - Instance, WorldContainer, + Instance, InstanceContainer, }; use bevy_app::{App, CoreSchedule, IntoSystemAppConfigs, Plugin}; use bevy_ecs::{ @@ -44,7 +44,7 @@ impl Plugin for PhysicsPlugin { /// gravity, collisions, and some other stuff. fn travel( mut query: Query<(&mut Physics, &mut Position, &Attributes, &WorldName), With>, - world_container: Res, + world_container: Res, ) { for (mut physics, mut position, attributes, world_name) in &mut query { let world_lock = world_container @@ -159,7 +159,7 @@ pub struct ForceJumpEvent(pub Entity); pub fn force_jump_listener( mut query: Query<(&mut Physics, &Position, &Sprinting, &WorldName)>, - world_container: Res, + world_container: Res, mut events: EventReader, ) { for event in events.iter() { @@ -306,7 +306,7 @@ mod tests { use azalea_core::{ChunkPos, ResourceLocation}; use azalea_world::{ entity::{EntityBundle, EntityPlugin, MinecraftEntityId}, - Chunk, PartialWorld, + Chunk, PartialInstance, }; use bevy_app::App; use bevy_time::fixed_timestep::FixedTime; @@ -318,14 +318,14 @@ mod tests { app.add_plugin(PhysicsPlugin) .add_plugin(EntityPlugin) .insert_resource(FixedTime::new(Duration::from_millis(50))) - .init_resource::(); + .init_resource::(); app } #[test] fn test_gravity() { let mut app = make_test_app(); - let _world_lock = app.world.resource_mut::().insert( + let _world_lock = app.world.resource_mut::().insert( ResourceLocation::new("minecraft:overworld").unwrap(), 384, -64, @@ -377,12 +377,12 @@ mod tests { #[test] fn test_collision() { let mut app = make_test_app(); - let world_lock = app.world.resource_mut::().insert( + let world_lock = app.world.resource_mut::().insert( ResourceLocation::new("minecraft:overworld").unwrap(), 384, -64, ); - let mut partial_world = PartialWorld::default(); + let mut partial_world = PartialInstance::default(); partial_world.chunks.set( &ChunkPos { x: 0, z: 0 }, @@ -436,12 +436,12 @@ mod tests { #[test] fn test_slab_collision() { let mut app = make_test_app(); - let world_lock = app.world.resource_mut::().insert( + let world_lock = app.world.resource_mut::().insert( ResourceLocation::new("minecraft:overworld").unwrap(), 384, -64, ); - let mut partial_world = PartialWorld::default(); + let mut partial_world = PartialInstance::default(); partial_world.chunks.set( &ChunkPos { x: 0, z: 0 }, @@ -490,12 +490,12 @@ mod tests { #[test] fn test_top_slab_collision() { let mut app = make_test_app(); - let world_lock = app.world.resource_mut::().insert( + let world_lock = app.world.resource_mut::().insert( ResourceLocation::new("minecraft:overworld").unwrap(), 384, -64, ); - let mut partial_world = PartialWorld::default(); + let mut partial_world = PartialInstance::default(); partial_world.chunks.set( &ChunkPos { x: 0, z: 0 }, @@ -543,12 +543,12 @@ mod tests { #[test] fn test_weird_wall_collision() { let mut app = make_test_app(); - let world_lock = app.world.resource_mut::().insert( + let world_lock = app.world.resource_mut::().insert( ResourceLocation::new("minecraft:overworld").unwrap(), 384, -64, ); - let mut partial_world = PartialWorld::default(); + let mut partial_world = PartialInstance::default(); partial_world.chunks.set( &ChunkPos { x: 0, z: 0 }, @@ -601,12 +601,12 @@ mod tests { #[test] fn test_negative_coordinates_weird_wall_collision() { let mut app = make_test_app(); - let world_lock = app.world.resource_mut::().insert( + let world_lock = app.world.resource_mut::().insert( ResourceLocation::new("minecraft:overworld").unwrap(), 384, -64, ); - let mut partial_world = PartialWorld::default(); + let mut partial_world = PartialInstance::default(); partial_world.chunks.set( &ChunkPos { x: -1, z: -1 }, diff --git a/azalea-protocol/src/packets/game/serverbound_client_information_packet.rs b/azalea-protocol/src/packets/game/serverbound_client_information_packet.rs index 65e13239..9cace991 100755 --- a/azalea-protocol/src/packets/game/serverbound_client_information_packet.rs +++ b/azalea-protocol/src/packets/game/serverbound_client_information_packet.rs @@ -1,8 +1,9 @@ use azalea_buf::{McBuf, McBufReadable, McBufWritable}; use azalea_core::FixedBitSet; use azalea_protocol_macros::ServerboundGamePacket; +use bevy_ecs::component::Component; -#[derive(Clone, Debug, McBuf, ServerboundGamePacket, PartialEq, Eq)] +#[derive(Clone, Debug, McBuf, ServerboundGamePacket, PartialEq, Eq, Component)] pub struct ServerboundClientInformationPacket { /// The locale of the client. pub language: String, diff --git a/azalea-world/src/container.rs b/azalea-world/src/container.rs index fdd89a75..c8af8c99 100644 --- a/azalea-world/src/container.rs +++ b/azalea-world/src/container.rs @@ -10,10 +10,10 @@ use std::{ use crate::{ChunkStorage, Instance}; -/// A container of [`World`]s. Worlds are stored as a Weak pointer here, so -/// if no clients are using a world it will be forgotten. +/// A container of [`Instance`]s (aka worlds). Instances are stored as a Weak +/// pointer here, so if no clients are using an instance it will be forgotten. #[derive(Default, Resource)] -pub struct WorldContainer { +pub struct InstanceContainer { // We just refer to the chunks here and don't include entities because there's not that many // cases where we'd want to get every entity in the world (just getting the entities in chunks // should work fine). @@ -29,9 +29,9 @@ pub struct WorldContainer { pub worlds: HashMap>>, } -impl WorldContainer { +impl InstanceContainer { pub fn new() -> Self { - WorldContainer { + InstanceContainer { worlds: HashMap::new(), } } diff --git a/azalea-world/src/entity/info.rs b/azalea-world/src/entity/info.rs index 19e87627..fdfe82c2 100644 --- a/azalea-world/src/entity/info.rs +++ b/azalea-world/src/entity/info.rs @@ -6,7 +6,7 @@ use crate::{ entity::{ self, add_dead, update_bounding_box, EntityUuid, MinecraftEntityId, Position, WorldName, }, - update_entity_by_id_index, update_uuid_index, PartialWorld, WorldContainer, + update_entity_by_id_index, update_uuid_index, InstanceContainer, PartialInstance, }; use azalea_core::ChunkPos; use bevy_app::{App, CoreSet, Plugin}; @@ -134,9 +134,9 @@ impl PartialEntityInfos { } } -/// A [`Command`] that applies a "relative update" to an entity, which means -/// this update won't be run multiple times by different clients in the same -/// world. +/// An [`EntityCommand`] that applies a "relative update" to an entity, which +/// means this update won't be run multiple times by different clients in the +/// same world. /// /// This is used to avoid a bug where when there's multiple clients in the same /// world and an entity sends a relative move packet to all clients, its @@ -146,7 +146,7 @@ impl PartialEntityInfos { /// other clients within render distance will get too. You usually don't need /// this when the change isn't relative either. pub struct RelativeEntityUpdate { - pub partial_world: Arc>, + pub partial_world: Arc>, // a function that takes the entity and updates it pub update: Box, } @@ -218,7 +218,7 @@ fn update_entity_chunk_positions( ), Changed, >, - world_container: Res, + world_container: Res, ) { for (entity, pos, last_pos, world_name) in query.iter_mut() { let world_lock = world_container.get(world_name).unwrap(); @@ -285,7 +285,7 @@ fn debug_detect_updates_received_on_local_entities( fn remove_despawned_entities_from_indexes( mut commands: Commands, mut entity_infos: ResMut, - world_container: Res, + world_container: Res, query: Query<(Entity, &EntityUuid, &Position, &WorldName, &LoadedBy), Changed>, ) { for (entity, uuid, position, world_name, loaded_by) in &query { diff --git a/azalea-world/src/world.rs b/azalea-world/src/world.rs index 7da9b869..e8d25032 100644 --- a/azalea-world/src/world.rs +++ b/azalea-world/src/world.rs @@ -4,7 +4,7 @@ use crate::{ }, iterators::ChunkIterator, palette::Palette, - ChunkStorage, PartialChunkStorage, WorldContainer, + ChunkStorage, InstanceContainer, PartialChunkStorage, }; use azalea_block::{BlockState, BlockStates}; use azalea_core::{BlockPos, ChunkPos}; @@ -21,24 +21,24 @@ use std::{ fmt::Debug, }; -/// PartialWorlds are usually owned by clients, and hold strong references to -/// chunks and entities in [`World`]s. +/// PartialInstances are usually owned by clients, and hold strong references to +/// chunks and entities in [`Instance`]s. /// /// Basically, they hold the chunks and entities that are within render /// distance but can still access chunks and entities owned by other -/// `PartialWorld`s that have the same `World`. +/// `PartialInstance`s that have the same `Instance`. /// -/// This is primarily useful for having multiple clients in the same world. -pub struct PartialWorld { +/// This is primarily useful for having multiple clients in the same Instance. +pub struct PartialInstance { pub chunks: PartialChunkStorage, /// Some metadata about entities, like what entities are in certain chunks. /// This does not contain the entity data itself, that's in the ECS. pub entity_infos: PartialEntityInfos, } -impl PartialWorld { +impl PartialInstance { pub fn new(chunk_radius: u32, owner_entity: Option) -> Self { - PartialWorld { + PartialInstance { chunks: PartialChunkStorage::new(chunk_radius), entity_infos: PartialEntityInfos::new(owner_entity), } @@ -59,7 +59,7 @@ pub fn deduplicate_entities( (Changed, Without), >, mut loaded_by_query: Query<&mut LoadedBy>, - world_container: Res, + world_container: Res, ) { // if this entity already exists, remove it for (new_entity, id, world_name) in query.iter_mut() { @@ -104,7 +104,7 @@ pub fn deduplicate_local_entities( (Entity, &MinecraftEntityId, &WorldName), (Changed, With), >, - world_container: Res, + world_container: Res, ) { // if this entity already exists, remove the old one for (new_entity, id, world_name) in query.iter_mut() { @@ -262,7 +262,7 @@ impl Instance { } } -impl Debug for PartialWorld { +impl Debug for PartialInstance { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.debug_struct("World") .field("chunk_storage", &self.chunks) @@ -271,8 +271,8 @@ impl Debug for PartialWorld { } } -impl Default for PartialWorld { - /// Creates a completely self-contained `PartialWorld`. This is only for +impl Default for PartialInstance { + /// Creates a completely self-contained `PartialInstance`. This is only for /// testing and shouldn't be used in actual code! fn default() -> Self { let chunk_storage = PartialChunkStorage::default(); @@ -290,7 +290,7 @@ pub fn update_entity_by_id_index( (Entity, &MinecraftEntityId, &WorldName, Option<&Local>), Changed, >, - world_container: Res, + world_container: Res, ) { for (entity, id, world_name, local) in query.iter_mut() { let world_lock = world_container.get(world_name).unwrap(); diff --git a/azalea/src/pathfinder/mod.rs b/azalea/src/pathfinder/mod.rs index 61a92038..9c06ebb8 100644 --- a/azalea/src/pathfinder/mod.rs +++ b/azalea/src/pathfinder/mod.rs @@ -20,7 +20,7 @@ use azalea_world::entity::metadata::Player; use azalea_world::entity::Local; use azalea_world::{ entity::{Physics, Position, WorldName}, - WorldContainer, + InstanceContainer, }; use bevy_tasks::{AsyncComputeTaskPool, Task}; use futures_lite::future; @@ -93,7 +93,7 @@ fn goto_listener( mut commands: Commands, mut events: EventReader, mut query: Query<(&Position, &WorldName)>, - world_container: Res, + world_container: Res, ) { let thread_pool = AsyncComputeTaskPool::get(); diff --git a/azalea/src/pathfinder/moves.rs b/azalea/src/pathfinder/moves.rs index 3639c091..6625581d 100644 --- a/azalea/src/pathfinder/moves.rs +++ b/azalea/src/pathfinder/moves.rs @@ -151,11 +151,11 @@ mod tests { use super::*; use azalea_block::BlockState; use azalea_core::ChunkPos; - use azalea_world::{Chunk, ChunkStorage, PartialWorld}; + use azalea_world::{Chunk, ChunkStorage, PartialInstance}; #[test] fn test_is_passable() { - let mut partial_world = PartialWorld::default(); + let mut partial_world = PartialInstance::default(); let mut chunk_storage = ChunkStorage::default(); partial_world.chunks.set( @@ -181,7 +181,7 @@ mod tests { #[test] fn test_is_solid() { - let mut partial_world = PartialWorld::default(); + let mut partial_world = PartialInstance::default(); let mut chunk_storage = ChunkStorage::default(); partial_world.chunks.set( &ChunkPos { x: 0, z: 0 }, @@ -206,7 +206,7 @@ mod tests { #[test] fn test_is_standable() { - let mut partial_world = PartialWorld::default(); + let mut partial_world = PartialInstance::default(); let mut chunk_storage = ChunkStorage::default(); partial_world.chunks.set( &ChunkPos { x: 0, z: 0 }, diff --git a/azalea/src/swarm/mod.rs b/azalea/src/swarm/mod.rs index 97020153..6fe11b7d 100644 --- a/azalea/src/swarm/mod.rs +++ b/azalea/src/swarm/mod.rs @@ -11,7 +11,7 @@ use azalea_protocol::{ resolver::{self, ResolverError}, ServerAddress, }; -use azalea_world::WorldContainer; +use azalea_world::InstanceContainer; use bevy_app::{App, Plugin, PluginGroup, PluginGroupBuilder}; use bevy_ecs::{component::Component, entity::Entity, system::Resource, world::World}; use futures::future::join_all; @@ -24,7 +24,7 @@ use tokio::sync::mpsc; /// A swarm is a way to conveniently control many bots at once, while also /// being able to control bots at an individual level when desired. /// -/// Swarms are created from [`azalea::swarm::SwarmBuilder`]. +/// Swarms are created from [`SwarmBuilder`]. /// /// The `S` type parameter is the type of the state for individual bots. /// It's used to make the [`Swarm::add`] function work. @@ -37,7 +37,7 @@ pub struct Swarm { // bot_datas: Arc>>, resolved_address: SocketAddr, address: ServerAddress, - pub world_container: Arc>, + pub world_container: Arc>, bots_tx: mpsc::UnboundedSender<(Option, Client)>, swarm_tx: mpsc::UnboundedSender, @@ -248,7 +248,7 @@ where // resolve the address let resolved_address = resolver::resolve_address(&address).await?; - let world_container = Arc::new(RwLock::new(WorldContainer::default())); + let world_container = Arc::new(RwLock::new(InstanceContainer::default())); // we can't modify the swarm plugins after this let (bots_tx, mut bots_rx) = mpsc::unbounded_channel();