M client/src/plugins/async_tasks/mod.rs => client/src/plugins/async_tasks/mod.rs +12 -1
@@ 29,6 29,9 @@ pub use req_game_mygames::GameMyGamesCallEvent;
mod req_game_details;
pub use req_game_details::GameDetailsCallEvent;
+mod parse_game_status;
+pub use parse_game_status::ParseGameStatusEvent;
+
pub struct AsyncTasksPlugin;
impl Plugin for AsyncTasksPlugin {
@@ 41,6 44,7 @@ impl Plugin for AsyncTasksPlugin {
.add_event::<GameFormingCallEvent>()
.add_event::<GameMyGamesCallEvent>()
.add_event::<GameDetailsCallEvent>()
+ .add_event::<ParseGameStatusEvent>()
.add_systems(
(
req_login::start_call,
@@ 57,7 61,14 @@ impl Plugin for AsyncTasksPlugin {
req_game_mygames::handle_call,
req_game_details::start_call,
req_game_details::handle_call,
+ )
+ .chain()
+ )
+ .add_systems(
+ (
+ parse_game_status::start_call,
+ parse_game_status::handle_call,
).chain()
- );
+ );
}
}
A client/src/plugins/async_tasks/parse_game_status.rs => client/src/plugins/async_tasks/parse_game_status.rs +59 -0
@@ 0,0 1,59 @@
+/*
+ * This file is part of laurelin_client
+ * Copyright (C) 2023 Jonni Liljamo <jonni@liljamo.com>
+ *
+ * Licensed under GPL-3.0-only.
+ * See LICENSE for licensing information.
+ */
+
+use crate::{
+ plugins::game::GameData, game_status::GameStatus, api::game::Game,
+};
+
+use bevy::{prelude::*, tasks::{Task, AsyncComputeTaskPool}};
+use futures_lite::future;
+
+#[derive(Component)]
+pub struct ParseGameStatus(Task<GameStatus>);
+
+#[derive(Clone)]
+pub struct ParseGameStatusEvent {
+ pub game: Game,
+}
+
+pub fn start_call(
+ mut commands: Commands,
+ mut start_ev_r: EventReader<ParseGameStatusEvent>,
+ ) {
+ for ev in start_ev_r.iter() {
+ let thread_pool = AsyncComputeTaskPool::get();
+ let ev = ev.clone();
+ let task = thread_pool.spawn(async move {
+ let res = GameStatus::new(&ev.game.actions.unwrap());
+
+ res
+ });
+ commands.spawn(ParseGameStatus(task));
+ }
+}
+
+pub fn handle_call(
+ mut commands: Commands,
+ mut tasks: Query<(Entity, &mut ParseGameStatus)>,
+ mut game_data: ResMut<GameData>,
+ ) {
+ match tasks.get_single_mut() {
+ Ok((entity, mut task)) => {
+ if let Some(response) = future::block_on(future::poll_once(&mut task.0)) {
+ game_data.game_status = Some(response);
+ game_data.parsing_data = false;
+
+ // remove the task
+ commands.entity(entity).remove::<ParseGameStatus>();
+ commands.entity(entity).despawn_recursive();
+ }
+ }
+ // NOTE: don't do anything if the wanted thingy doesn't exist
+ _ => {}
+ }
+}
M client/src/plugins/game/mod.rs => client/src/plugins/game/mod.rs +4 -0
@@ 28,6 28,8 @@ impl Plugin for GamePlugin {
pub struct GameData {
pub game: Option<Game>,
pub game_status: Option<GameStatus>,
+
+ pub parsing_data: bool,
}
impl Default for GameData {
@@ 35,6 37,8 @@ impl Default for GameData {
Self {
game: None,
game_status: None,
+
+ parsing_data: false,
}
}
}
M client/src/plugins/game/ui/mod.rs => client/src/plugins/game/ui/mod.rs +12 -2
@@ 9,7 9,7 @@
use bevy::prelude::*;
use bevy_egui::{egui, EguiContexts};
-use crate::{plugins::GameDetailsCallEvent, Global};
+use crate::{plugins::{GameDetailsCallEvent, ParseGameStatusEvent}, Global};
use super::GameData;
@@ 19,6 19,7 @@ pub fn ui(
global: Res<Global>,
mut game_data: ResMut<GameData>,
mut details_ev_w: EventWriter<GameDetailsCallEvent>,
+ mut parse_ev_w: EventWriter<ParseGameStatusEvent>,
) {
egui::Window::new("Game Details")
.show(contexts.ctx_mut(), |ui| {
@@ 27,7 28,16 @@ pub fn ui(
return;
};
let Some(status) = &game_data.game_status else {
- // early return if game_status is None
+ if game_data.parsing_data {
+ // early return if game_status is None, and we're parsing it
+ return;
+ }
+
+ // since we're not already parsing the data, we start it
+ game_data.parsing_data = true;
+ parse_ev_w.send(ParseGameStatusEvent {
+ game: game_data.game.as_ref().unwrap().clone(),
+ });
return;
};