use std::time::Duration;
use bevy::app::ScheduleRunnerPlugin;
use bevy::log::LogPlugin;
use bevy::prelude::*;
use bevy_net_backend::prelude::*;
use serde::Deserialize;
#[allow(dead_code)]
#[path = "mock_server.rs"]
mod mock_server;
#[derive(Deserialize, Clone, Debug)]
struct Character {
id: u32,
name: String,
class: String,
level: u32,
}
#[derive(Resource)]
struct Waiting(RequestId);
fn main() -> AppExit {
let (base_url, _mock) = match std::env::var("BACKEND_URL") {
Ok(url) => (url, None),
Err(_) => match mock_server::MockServer::start() {
Ok(mock) => (mock.url(), Some(mock)),
Err(e) => {
eprintln!("could not start the mock server: {e}");
return AppExit::error();
}
},
};
App::new()
.add_plugins((
MinimalPlugins.set(ScheduleRunnerPlugin::run_loop(Duration::from_millis(10))),
LogPlugin::default(),
BackendPlugin::new(HttpConfig::new(base_url).with_timeout(Duration::from_secs(5))),
))
.add_json_response::<Character>()
.add_systems(Startup, ask)
.add_systems(Update, (show, give_up))
.run()
}
fn ask(backend: Res<HttpClient>, mut commands: Commands) {
let id = backend.get_json::<Character>("/characters/1");
commands.insert_resource(Waiting(id));
}
fn show(mut answers: MessageReader<JsonResponse<Character>>, waiting: Option<Res<Waiting>>, mut exit: MessageWriter<AppExit>) {
let Some(waiting) = waiting else { return };
for answer in answers.read().filter(|a| a.id == waiting.0) {
match &answer.result {
Ok(character) => {
info!("character #{}: {} the {} (level {})", character.id, character.name, character.class, character.level);
exit.write(AppExit::Success);
}
Err(error) => {
let body = error.response().map(|r| r.text()).unwrap_or_default();
error!("the request failed: {error} {body}");
exit.write(AppExit::error());
}
}
}
}
fn give_up(time: Res<Time<Real>>, mut exit: MessageWriter<AppExit>) {
if time.elapsed() > Duration::from_secs(10) {
error!("no answer after 10 s");
exit.write(AppExit::error());
}
}