aboutsummaryrefslogtreecommitdiff
path: root/azalea/src
diff options
context:
space:
mode:
authormat <git@matdoes.dev>2024-02-24 21:03:02 -0600
committermat <git@matdoes.dev>2024-02-24 21:03:02 -0600
commit13426b035e43c4435854f175155439ab28a18544 (patch)
tree20b6c64ccf6947320f926bb3bc0951971d5c4c22 /azalea/src
parentc38957374c288eb41b7dbd905071a469c7bbb2b1 (diff)
downloadazalea-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.rs1
-rw-r--r--azalea/src/pathfinder/simulation.rs163
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()
+ }
+}