#[cfg(feature = "native")]
use std::sync::Arc;
#[cfg(feature = "native")]
use anyhow::{anyhow, Context, Result};
#[cfg(feature = "native")]
use arora_bridge::Bridge;
#[cfg(feature = "native")]
use arora_hal::Hal;
#[cfg(feature = "native")]
use arora_simple_data_store::SimpleDataStore;
#[cfg(feature = "native")]
use crate::runtime::Runtime;
#[cfg(feature = "native")]
use crate::Arora;
#[cfg(feature = "native")]
pub fn run() -> Result<()> {
run_with_hal(Arc::new(arora_hal::FakeHal::new()))
}
#[cfg(all(feature = "native", not(feature = "studio-bridge")))]
pub fn run_with_hal(hal: Arc<dyn Hal>) -> Result<()> {
let _ = env_logger::try_init();
run_with_bridge_builder(hal, SimpleDataStore::new(), || async {
let server = Arc::new(arora_websocket::AroraWSServer::new(
arora_websocket::ServerConfig::default(),
));
let bridge = arora_websocket::bridge::WsBridge::new(server.clone()).await;
tokio::spawn(async move {
if let Err(e) = server.run(arora_websocket::CancellationToken::new()).await {
log::error!("local bridge server stopped: {e:?}");
}
});
println!("arora: serving the local bridge on ws://127.0.0.1:9000");
let bridge: Arc<dyn Bridge> = Arc::new(bridge);
Ok(bridge)
})
}
#[cfg(feature = "studio-bridge")]
pub fn run_with_hal(hal: Arc<dyn Hal>) -> Result<()> {
crate::studio::run_with_hal(hal)
}
#[cfg(feature = "native")]
pub fn run_with(hal: Arc<dyn Hal>, bridge: Arc<dyn Bridge>, store: SimpleDataStore) -> Result<()> {
run_with_bridge_builder(hal, store, move || async move { Ok(bridge) })
}
#[cfg(feature = "native")]
pub fn run_with_bridge_builder<F, Fut>(
hal: Arc<dyn Hal>,
store: SimpleDataStore,
make_bridge: F,
) -> Result<()>
where
F: FnOnce() -> Fut,
Fut: std::future::Future<Output = Result<Arc<dyn Bridge>>>,
{
let tokio = tokio::runtime::Runtime::new().context("failed to start Tokio runtime")?;
let (mut runtime, io) = tokio.block_on(async {
let bridge = make_bridge().await.context("failed to build the bridge")?;
let arora = Arora::start().await.context("failed to start Arora")?;
let store: Arc<dyn arora_types::data::DataStore> = Arc::new(store);
Ok::<_, anyhow::Error>(Runtime::with_io_in(arora, hal, bridge, store))
})?;
println!("arora: engine started; native behavior-tree control nodes ready.");
if let Some(path) = std::env::args().nth(1) {
let xml = std::fs::read_to_string(&path)
.with_context(|| format!("could not read Groot file {path}"))?;
runtime
.queue_groot_xml(&xml)
.map_err(|e| anyhow!("failed to queue behavior tree from {path}: {e}"))?;
println!("arora: queued behavior tree from {path}");
}
tokio.spawn(io);
println!("arora: running — Ctrl-C to stop.");
runtime.run().map_err(|e| anyhow!("runtime error: {e}"))
}