插件配置调度

一般的plugin自己就决定了在哪个调度中执行system. 灵活性高一点的plugin则将决定权交给开发者.

下面这段代码非常有意思,将调度做为Plugin的配置进行动态设置.

声明:schedule: Interned<dyn ScheduleLabel>, 使用:schedule.intern().

#[derive(Debug, Clone, Reflect)]
#[reflect(from_reflect = false)]
pub struct BigBrainPlugin {
      #[reflect(ignore)]
    schedule: Interned<dyn ScheduleLabel>,
      #[reflect(ignore)]
    cleanup_schedule: Interned<dyn ScheduleLabel>,
}

impl BigBrainPlugin {
    /// Create the BigBrain plugin which runs the scorers, thinker and actions in the specified
    /// schedule
    pub fn new(schedule: impl ScheduleLabel) -> Self {
        Self {
            schedule: schedule.intern(),
            cleanup_schedule: Last.intern(),
        }
    }

    /// Overwrite the Schedule that is used to run cleanup tasks. By default this happens in Last.
    pub fn set_cleanup_schedule(mut self, cleanup_schedule: impl ScheduleLabel) -> Self {
        self.cleanup_schedule = cleanup_schedule.intern();
        self
    }
}

impl Plugin for BigBrainPlugin {
      fn build(&self, app: &mut App) {
        app.configure_sets(
            self.schedule.intern(),
            (
                BigBrainSet::Scorers,
                BigBrainSet::Thinkers,
                BigBrainSet::Actions,
            )
                  .chain(),
        )
          .configure_sets(self.cleanup_schedule.intern(), BigBrainSet::Cleanup)
          .add_systems(
            self.schedule.intern(),
            (
                scorers::fixed_score_system,
                scorers::measured_scorers_system,
                scorers::all_or_nothing_system,
                scorers::sum_of_scorers_system,
                scorers::product_of_scorers_system,
                scorers::winning_scorer_system,
                scorers::evaluating_scorer_system,
            )
                  .in_set(BigBrainSet::Scorers),
        )
            .add_systems(
            self.schedule.intern(),
            thinker::thinker_system.in_set(BigBrainSet::Thinkers),
        )
            .add_systems(
            self.schedule.intern(),
            (actions::steps_system, actions::concurrent_system).in_set(BigBrainSet::Actions),
        )
            .add_systems(
            self.cleanup_schedule.intern(),
            (
                thinker::thinker_component_attach_system,
                thinker::thinker_component_detach_system,
                thinker::actor_gone_cleanup,
            )
                  .in_set(BigBrainSet::Cleanup),
        );
    }
}

/// [`BigBrainPlugin`] system sets. Use these to schedule your own
/// actions/scorers/etc.
#[derive(Clone, Debug, Hash, Eq, PartialEq, SystemSet, Reflect)]
pub enum BigBrainSet {
      /// Scorers are evaluated in this set.
    Scorers,
      /// Actions are executed in this set.
    Actions,
      /// Thinkers run their logic in this set.
    Thinkers,
      /// Various internal cleanup items run in this final set.
    Cleanup,
}

中间一些东西可以简写的:

/// A shorthand for `Interned<dyn SystemSet>`.
pub type InternedSystemSet = Interned<dyn SystemSet>;
/// A shorthand for `Interned<dyn ScheduleLabel>`.
pub type InternedScheduleLabel = Interned<dyn ScheduleLabel>;