From 33d68894db843c7d68efc8399a3041264be8e548 Mon Sep 17 00:00:00 2001 From: Victor Bjelkholm Date: Fri, 9 Aug 2024 14:46:04 +0200 Subject: [PATCH] Tiny refactor + begin resman example --- crates/bevy_dogoap/examples/miner.rs | 1 + crates/bevy_dogoap/examples/resman.rs | 198 ++++++++++++++++---------- crates/bevy_dogoap/src/macros.rs | 9 ++ crates/bevy_dogoap/src/prelude.rs | 2 +- crates/bevy_dogoap/src/traits.rs | 10 +- web-src/index.html | 64 +-------- web-src/style.css | 54 +++++++ 7 files changed, 202 insertions(+), 136 deletions(-) create mode 100644 web-src/style.css diff --git a/crates/bevy_dogoap/examples/miner.rs b/crates/bevy_dogoap/examples/miner.rs index 28aa2c3..17d0d37 100644 --- a/crates/bevy_dogoap/examples/miner.rs +++ b/crates/bevy_dogoap/examples/miner.rs @@ -818,6 +818,7 @@ fn print_current_local_state( Option<&GoToSmelterAction>, Option<&GoToMerchantAction>, )>, + // action_query: Query<&dyn ActionComponent>, mut q_child: Query<&mut Text, With>, ) { for (entity, hunger, energy, has_ore, has_metal, gold_amount, children) in query.iter() { diff --git a/crates/bevy_dogoap/examples/resman.rs b/crates/bevy_dogoap/examples/resman.rs index 2d5ff3b..237a58d 100644 --- a/crates/bevy_dogoap/examples/resman.rs +++ b/crates/bevy_dogoap/examples/resman.rs @@ -23,7 +23,15 @@ use dogoap::prelude::*; fn main() { let mut app = App::new(); - register_components!(app, vec![Thirst, CarryingItem]); + // Customer components + actions + register_components!(app, vec![Thirst, CarryingItem, PlacedOrder, OrderReady]); + register_actions!( + app, + vec![DrinkLemonade, PickupLemonade, WaitForOrder, PlaceOrder] + ); + // Worker components + actions + register_components!(app, vec![Energy]); + register_actions!(app, vec![Rest]); app.add_plugins(DefaultPlugins.set(WindowPlugin { primary_window: Some(Window { @@ -40,21 +48,41 @@ fn main() { .run(); } -// LocalFields +// LocalFields for customer #[derive(Component, Clone, DatumComponent)] struct Thirst(f64); +#[derive(Component, Clone, EnumComponent)] +struct CarryingItem(Item); + +#[derive(Component, Clone, DatumComponent)] +struct PlacedOrder(bool); + #[derive(Component, Clone, DatumComponent)] -struct CarryingItem(usize); // `Items::Lemonade as usize` for example +struct OrderReady(bool); + +// Actions for customer -// Actions +#[derive(Component, Clone, Default, ActionComponent)] +struct DrinkLemonade; + +#[derive(Component, Clone, Default, ActionComponent)] +struct PickupLemonade; #[derive(Component, Clone, Default, ActionComponent)] -struct DrinkLemonade(); +struct WaitForOrder; #[derive(Component, Clone, Default, ActionComponent)] -struct PickupLemonade(); +struct PlaceOrder; + +// DatumComponents for worker + +#[derive(Component, Clone, DatumComponent)] +struct Energy(f64); + +#[derive(Component, Clone, Default, ActionComponent)] +struct Rest; // Markers @@ -67,7 +95,7 @@ struct Customer; #[derive(Component)] struct Worker; -#[derive(Clone, Default, Reflect)] +#[derive(Clone, Default, Copy, Reflect)] enum Item { #[default] Nothing, @@ -87,59 +115,56 @@ struct StateDebugText; fn setup(mut commands: Commands) { // Spawn customers for _i in 0..1 { - let goal = Goal::new().with_req(&Thirst::key(), Compare::LessThanEquals(Datum::F64(1.0))); - - let goals = vec![goal.clone()]; + let goal = Goal::from_reqs(&[Thirst::is_less(1.0)]); // Requires us to carry a lemonade, results in us having 10 less thirst + carrying Nothing - let drink_lemonade_action = Action::new(&DrinkLemonade::key()) - .with_precondition( - &CarryingItem::key(), - Compare::Equals(Datum::Enum(Item::Lemonade as usize)), - ) - .with_effect( - Effect::new(&DrinkLemonade::key()) - .with_mutator(Mutator::Set( - CarryingItem::key(), - Datum::Enum(Item::Nothing as usize), - )) - .with_mutator(Mutator::Decrement(Thirst::key(), Datum::F64(10.0))), - ); + let drink_lemonade_action = DrinkLemonade::new() + .add_precondition(CarryingItem::is(Item::Lemonade)) + .add_mutator(CarryingItem::set(Item::Nothing)) + .add_mutator(Thirst::decrease(10.0)); // Requires us to not be carrying nothing, and leads to us having a lemonade - let pickup_lemonade_action = Action::new(&PickupLemonade::key()) - .with_precondition( - &CarryingItem::key(), - Compare::Equals(Datum::Enum(Item::Nothing as usize)), - ) - .with_effect( - Effect::new(&PickupLemonade::key()).with_mutator(Mutator::Set( - CarryingItem::key(), - Datum::Enum(Item::Lemonade as usize), - )), - ); - - let actions_map = create_action_map!( - (DrinkLemonade, drink_lemonade_action), - (PickupLemonade, pickup_lemonade_action) - ); - - let initial_state = (Thirst(0.0), CarryingItem(Item::Nothing as usize)); - let state = create_state!(Thirst(0.0), CarryingItem(Item::Nothing as usize)); - - let mut planner = Planner::new(state, goals, actions_map); + let pickup_lemonade_action = PickupLemonade::new() + .add_precondition(CarryingItem::is(Item::Nothing)) + .add_mutator(CarryingItem::set(Item::Lemonade)); + + let wait_for_order_action = WaitForOrder::new() + .add_precondition(PlacedOrder::is(true)) + .add_precondition(OrderReady::is(false)) + .add_mutator(OrderReady::set(true)); + + let place_order_action = PlaceOrder::new() + .add_precondition(PlacedOrder::is(false)) + .add_mutator(PlacedOrder::set(true)); + + // Drink Lemonade + // Pickup Lemonade + // Wait for Order + // Place Order + // Go To Order Desk + + let (mut planner, components) = create_planner!({ + actions: [ + (DrinkLemonade, drink_lemonade_action), + (PickupLemonade, pickup_lemonade_action) + ], + state: [Thirst(0.0), CarryingItem(Item::Nothing)], + goals: [goal], + }); planner.remove_goal_on_no_plan_found = false; // Don't remove the goal planner.always_plan = true; // Re-calculate our plan whenever we can planner.current_goal = Some(goal.clone()); + let t = Transform::from_scale(Vec3::splat(2.0)); + commands .spawn(( Agent, Name::new("Customer"), Customer, planner, - initial_state, + components, TransformBundle::from(Transform::from_xyz(-200.0, -100.0, 1.0)), )) .with_children(|subcommands| { @@ -164,11 +189,25 @@ fn setup(mut commands: Commands) { // Spawn worker for _i in 0..1 { + let goal = Goal::from_reqs(&[Energy::is_more(1.0)]); + + let rest_action = Rest::new() + .add_precondition(Energy::is_less(10.0)) + .add_mutator(Energy::increase(50.0)); + + let (planner, components) = create_planner!({ + actions: [(Rest, rest_action)], + state: [Energy(50.0)], + goals: [goal], + }); + commands .spawn(( Agent, Name::new("Worker"), Worker, + planner, + components, TransformBundle::from(Transform::from_xyz(0.0, 0.0, 1.0)), )) .with_children(|subcommands| { @@ -214,7 +253,7 @@ fn handle_pickup_lemonade( match progresses.get_mut(&entity) { Some(progress) => { if progress.tick(time.delta()).just_finished() { - state.0 = Item::Lemonade as usize; + state.0 = Item::Lemonade; commands.entity(entity).remove::(); progresses.remove(&entity); } else { @@ -239,7 +278,7 @@ fn handle_drink_lemonade( match progresses.get_mut(&entity) { Some(progress) => { if progress.tick(time.delta()).just_finished() { - state.0 = Item::Nothing as usize; + state.0 = Item::Nothing; thirst.0 = (thirst.0 - 5.0).max(0.0); commands.entity(entity).remove::(); @@ -266,9 +305,10 @@ fn update_thirst(time: Res