oxygengine_overworld/systems/
board.rs1use crate::{components::board_avatar::*, resources::board::*};
2use oxygengine_core::{
3 app::AppLifeCycle,
4 ecs::{life_cycle::EntityChanges, Comp, Entity, Universe, WorldRef},
5};
6use std::collections::HashMap;
7
8#[derive(Debug, Default)]
9pub struct BoardSystemCache {
10 avatars: HashMap<Entity, BoardToken>,
11 avatars_table: HashMap<BoardToken, Entity>,
12}
13
14impl BoardSystemCache {
15 pub fn token_by_entity(&self, entity: Entity) -> Option<BoardToken> {
16 self.avatars.get(&entity).cloned()
17 }
18
19 pub fn entity_by_token(&self, token: BoardToken) -> Option<Entity> {
20 self.avatars_table.get(&token).cloned()
21 }
22}
23
24pub type BoardSystemResources<'a> = (
25 WorldRef,
26 &'a AppLifeCycle,
27 &'a EntityChanges,
28 &'a mut Board,
29 &'a mut BoardSystemCache,
30 Comp<&'a mut BoardAvatar>,
31);
32
33pub fn board_system(universe: &mut Universe) {
34 let (world, lifecycle, changes, mut board, mut cache, ..) =
35 universe.query_resources::<BoardSystemResources>();
36
37 let dt = lifecycle.delta_time_seconds();
38
39 for entity in changes.despawned() {
40 if let Some(token) = cache.avatars.remove(&entity) {
41 board.release_token(token);
42 cache.avatars_table.remove(&token);
43 }
44 }
45
46 for (entity, avatar) in world.query::<&mut BoardAvatar>().iter() {
47 avatar.has_lately_completed_action = false;
48 if avatar.token.is_none() {
49 if let Ok(token) = board.acquire_token(avatar.location()) {
50 avatar.token = Some(token);
51 cache.avatars.insert(entity, token);
52 cache.avatars_table.insert(token, entity);
53 }
54 }
55 if let Some(token) = avatar.token {
56 if let Some((action, time, completed)) = &mut avatar.active_action {
57 if let Some(location) = board.token_location(token) {
58 *time += dt;
59 let duration = action.duration();
60 let (dx, dy) = board.location_relative(avatar.location, location);
61 if dx != 0 || dy != 0 {
62 avatar.direction = match (dx.signum(), dy.signum()) {
63 (-1, -1) => Some(BoardDirection::NorthWest),
64 (0, -1) => Some(BoardDirection::North),
65 (1, -1) => Some(BoardDirection::NorthEast),
66 (-1, 0) => Some(BoardDirection::West),
67 (1, 0) => Some(BoardDirection::East),
68 (-1, 1) => Some(BoardDirection::SouthWest),
69 (0, 1) => Some(BoardDirection::South),
70 (1, 1) => Some(BoardDirection::SouthEast),
71 _ => avatar.direction,
72 };
73 }
74 if *time >= duration {
75 avatar.location = location;
76 *time = duration;
77 *completed = true;
78 avatar.has_lately_completed_action = true;
79 }
80 }
81 if !*completed {
82 continue;
83 }
84 }
85 avatar.active_action = None;
86 if let Some(action) = avatar.actions_queue.pop_front() {
87 let success = match &action {
88 BoardAvatarAction::Move { x, y, .. } => board.move_token(token, *x, *y).is_ok(),
89 BoardAvatarAction::MoveStep { direction, .. } => {
90 board.move_step_token(token, *direction).is_ok()
91 }
92 BoardAvatarAction::Teleport { location, .. } => {
93 board.teleport_token(token, *location).is_ok()
94 }
95 };
96 if success {
97 avatar.active_action = Some((action, 0.0, false));
98 } else {
99 avatar.actions_queue.clear();
100 avatar.active_action = None;
101 }
102 }
103 }
104 }
105}