diff options
| author | mat <git@matdoes.dev> | 2024-02-24 21:03:02 -0600 |
|---|---|---|
| committer | mat <git@matdoes.dev> | 2024-02-24 21:03:02 -0600 |
| commit | 13426b035e43c4435854f175155439ab28a18544 (patch) | |
| tree | 20b6c64ccf6947320f926bb3bc0951971d5c4c22 /azalea/src | |
| parent | c38957374c288eb41b7dbd905071a469c7bbb2b1 (diff) | |
| download | azalea-drasl-13426b035e43c4435854f175155439ab28a18544.tar.xz | |
add Display for Vec3, add SimulationSet, and add EntityChunkPos component
Diffstat (limited to 'azalea/src')
| -rw-r--r-- | azalea/src/lib.rs | 1 | ||||
| -rw-r--r-- | azalea/src/pathfinder/simulation.rs | 163 |
2 files changed, 107 insertions, 57 deletions
diff --git a/azalea/src/lib.rs b/azalea/src/lib.rs index fd2cb83a..84c215d5 100644 --- a/azalea/src/lib.rs +++ b/azalea/src/lib.rs @@ -29,6 +29,7 @@ pub use azalea_core::{ resource_location::ResourceLocation, }; pub use azalea_entity as entity; +pub use azalea_physics as physics; pub use azalea_protocol as protocol; pub use azalea_registry as registry; pub use azalea_world as world; diff --git a/azalea/src/pathfinder/simulation.rs b/azalea/src/pathfinder/simulation.rs index ab3b340e..bea99e93 100644 --- a/azalea/src/pathfinder/simulation.rs +++ b/azalea/src/pathfinder/simulation.rs @@ -7,7 +7,7 @@ use azalea_client::{ }; use azalea_core::{position::Vec3, resource_location::ResourceLocation, tick::GameTick}; use azalea_entity::{ - attributes::AttributeInstance, Attributes, EntityDimensions, Physics, Position, + attributes::AttributeInstance, Attributes, EntityDimensions, LookDirection, Physics, Position, }; use azalea_world::{ChunkStorage, Instance, InstanceContainer, MinecraftEntityId, PartialInstance}; use bevy_app::App; @@ -20,6 +20,7 @@ pub struct SimulatedPlayerBundle { pub position: Position, pub physics: Physics, pub physics_state: PhysicsState, + pub look_direction: LookDirection, pub attributes: Attributes, pub inventory: InventoryComponent, } @@ -35,6 +36,7 @@ impl SimulatedPlayerBundle { position: Position::new(position), physics: Physics::new(dimensions, &position), physics_state: PhysicsState::default(), + look_direction: LookDirection::new(0.0, 0.0), attributes: Attributes { speed: AttributeInstance::new(0.1), attack_speed: AttributeInstance::new(4.0), @@ -44,6 +46,77 @@ impl SimulatedPlayerBundle { } } +fn simulation_instance_name() -> ResourceLocation { + ResourceLocation::new("azalea:simulation") +} + +fn create_simulation_instance(chunks: ChunkStorage) -> (App, Arc<RwLock<Instance>>) { + let instance_name = simulation_instance_name(); + + let instance = Arc::new(RwLock::new(Instance { + chunks, + ..Default::default() + })); + + let mut app = App::new(); + // we don't use all the default azalea plugins because we don't need all of them + app.add_plugins(( + azalea_physics::PhysicsPlugin, + azalea_entity::EntityPlugin, + azalea_client::movement::PlayerMovePlugin, + super::PathfinderPlugin, + crate::BotPlugin, + azalea_client::task_pool::TaskPoolPlugin::default(), + // for mining + azalea_client::inventory::InventoryPlugin, + azalea_client::mining::MinePlugin, + azalea_client::interact::InteractPlugin, + )) + .insert_resource(InstanceContainer { + instances: [(instance_name.clone(), Arc::downgrade(&instance.clone()))] + .iter() + .cloned() + .collect(), + }) + .add_event::<SendPacketEvent>(); + + app.edit_schedule(bevy_app::Main, |schedule| { + schedule.set_executor_kind(bevy_ecs::schedule::ExecutorKind::SingleThreaded); + }); + + (app, instance) +} + +fn create_simulation_player( + ecs: &mut World, + instance: Arc<RwLock<Instance>>, + player: SimulatedPlayerBundle, +) -> Entity { + let instance_name = simulation_instance_name(); + + let mut entity = ecs.spawn(( + MinecraftEntityId(0), + azalea_entity::LocalEntity, + azalea_entity::metadata::PlayerMetadataBundle::default(), + azalea_entity::EntityBundle::new( + Uuid::nil(), + *player.position, + azalea_registry::EntityKind::Player, + instance_name, + ), + azalea_client::InstanceHolder { + // partial_instance is never actually used by the pathfinder so + partial_instance: Arc::new(RwLock::new(PartialInstance::default())), + instance: instance.clone(), + }, + InventoryComponent::default(), + )); + entity.insert(player); + + let entity_id = entity.id(); + entity_id +} + /// Simulate the Minecraft world to see if certain movements would be possible. pub struct Simulation { pub app: App, @@ -53,71 +126,47 @@ pub struct Simulation { impl Simulation { pub fn new(chunks: ChunkStorage, player: SimulatedPlayerBundle) -> Self { - let instance_name = ResourceLocation::new("azalea:simulation"); - - let instance = Arc::new(RwLock::new(Instance { - chunks, - ..Default::default() - })); - - let mut app = App::new(); - // we don't use all the default azalea plugins because we don't need all of them - app.add_plugins(( - azalea_physics::PhysicsPlugin, - azalea_entity::EntityPlugin, - azalea_client::movement::PlayerMovePlugin, - super::PathfinderPlugin, - crate::BotPlugin, - azalea_client::task_pool::TaskPoolPlugin::default(), - // for mining - azalea_client::inventory::InventoryPlugin, - azalea_client::mining::MinePlugin, - azalea_client::interact::InteractPlugin, - )) - .insert_resource(InstanceContainer { - instances: [(instance_name.clone(), Arc::downgrade(&instance.clone()))] - .iter() - .cloned() - .collect(), - }) - .add_event::<SendPacketEvent>(); - - app.edit_schedule(bevy_app::Main, |schedule| { - schedule.set_executor_kind(bevy_ecs::schedule::ExecutorKind::SingleThreaded); - }); - - let mut entity = app.world.spawn(( - MinecraftEntityId(0), - azalea_entity::LocalEntity, - azalea_entity::metadata::PlayerMetadataBundle::default(), - azalea_entity::EntityBundle::new( - Uuid::nil(), - *player.position, - azalea_registry::EntityKind::Player, - instance_name, - ), - azalea_client::InstanceHolder { - // partial_instance is never actually used by the pathfinder so - partial_instance: Arc::new(RwLock::new(PartialInstance::default())), - instance: instance.clone(), - }, - InventoryComponent::default(), - )); - entity.insert(player); - - let entity_id = entity.id(); - + let (mut app, instance) = create_simulation_instance(chunks); + let entity = create_simulation_player(&mut app.world, instance.clone(), player); Self { app, - entity: entity_id, + entity, _instance: instance, } } + pub fn tick(&mut self) { - self.app.world.run_schedule(GameTick); self.app.update(); + self.app.world.run_schedule(GameTick); } pub fn position(&self) -> Vec3 { **self.app.world.get::<Position>(self.entity).unwrap() } } + +/// A set of simulations, useful for efficiently doing multiple simulations. +pub struct SimulationSet { + pub app: App, + instance: Arc<RwLock<Instance>>, +} +impl SimulationSet { + pub fn new(chunks: ChunkStorage) -> Self { + let (app, instance) = create_simulation_instance(chunks); + Self { app, instance } + } + pub fn tick(&mut self) { + self.app.update(); + self.app.world.run_schedule(GameTick); + } + + pub fn spawn(&mut self, player: SimulatedPlayerBundle) -> Entity { + create_simulation_player(&mut self.app.world, self.instance.clone(), player) + } + pub fn despawn(&mut self, entity: Entity) { + self.app.world.despawn(entity); + } + + pub fn position(&self, entity: Entity) -> Vec3 { + **self.app.world.get::<Position>(entity).unwrap() + } +} |
