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