use super::hook::{ActionHook, DefaultActionHook};
use super::systems::{ActionResetSystem, ActionSystem};
use super::ActionPoints;
use crate::plugin::{Plugin, PluginBuilder, PluginBuilderExt};
use async_trait::async_trait;
use std::sync::Arc;
#[derive(Debug, Clone)]
pub struct ActionConfig {
pub max_per_period: u32,
}
impl Default for ActionConfig {
fn default() -> Self {
Self { max_per_period: 3 }
}
}
impl crate::resources::Resource for ActionConfig {}
pub struct ActionPlugin {
config: ActionConfig,
hook: Arc<dyn ActionHook>,
}
impl ActionPlugin {
pub fn new(config: ActionConfig) -> Self {
Self {
config,
hook: Arc::new(DefaultActionHook),
}
}
pub fn with_defaults() -> Self {
Self {
config: ActionConfig::default(),
hook: Arc::new(DefaultActionHook),
}
}
pub fn with_hook(mut self, hook: impl ActionHook + 'static) -> Self {
self.hook = Arc::new(hook);
self
}
}
impl Default for ActionPlugin {
fn default() -> Self {
Self::with_defaults()
}
}
#[async_trait]
impl Plugin for ActionPlugin {
fn name(&self) -> &'static str {
"issun:action"
}
fn build(&self, builder: &mut dyn PluginBuilder) {
let points = ActionPoints::new(self.config.max_per_period);
builder.register_runtime_state(points);
builder.register_system(Box::new(ActionSystem::new(Arc::clone(&self.hook))));
builder.register_system(Box::new(ActionResetSystem::new(Arc::clone(&self.hook))));
builder.register_resource(self.config.clone());
}
fn dependencies(&self) -> Vec<&'static str> {
vec!["issun:time"] }
async fn initialize(&mut self) {
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_plugin_name() {
let plugin = ActionPlugin::default();
assert_eq!(plugin.name(), "issun:action");
}
#[test]
fn test_plugin_with_custom_config() {
let config = ActionConfig { max_per_period: 5 };
let plugin = ActionPlugin::new(config.clone());
assert_eq!(plugin.config.max_per_period, 5);
}
#[test]
fn test_plugin_default() {
let plugin = ActionPlugin::default();
assert_eq!(plugin.config.max_per_period, 3);
}
#[test]
fn test_plugin_dependencies() {
let plugin = ActionPlugin::default();
assert_eq!(plugin.dependencies(), vec!["issun:time"]);
}
#[test]
fn test_plugin_with_hook() {
let plugin =
ActionPlugin::new(ActionConfig { max_per_period: 3 }).with_hook(DefaultActionHook);
assert_eq!(plugin.config.max_per_period, 3);
}
}