oxygengine_overworld/systems/
board.rs

1use 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}