twgame 0.11.0

DDNet physics implementation
Documentation
use super::Tees;
use crate::{
    entities::tee::Tee,
    ids::{PlayerUid, TeamId},
};
use twgame_core::twsnap::time::{Duration, Instant};

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TeamKind {
    Team0,
    NonTeam0,
    // TODO: Solo,
}

#[derive(Debug)]
pub struct Globals {
    locked: bool,
    team_kind: TeamKind,
    team_id: TeamId,
    pub(super) start_time: Option<Instant>,
    pub(super) all_finished: bool,
}

impl Globals {
    pub(super) fn new(team_id: TeamId, team_kind: TeamKind) -> Self {
        Self {
            team_id,
            locked: false,
            team_kind,
            start_time: None,
            all_finished: false,
        }
    }
}

// accessible to Team struct
impl Globals {
    pub(super) fn toggle_lock(&mut self) {
        self.locked = !self.locked;
    }

    pub(super) fn set_lock(&mut self, locked: bool) {
        self.locked = locked;
    }
}

// accessible to team and entities
impl Globals {
    pub fn team_id(&self) -> TeamId {
        self.team_id
    }
    pub fn is_locked(&self) -> bool {
        self.team_kind == TeamKind::NonTeam0 && self.locked
    }

    pub fn kill_propagates(&self) -> bool {
        self.is_locked() && self.start_time.is_some()
    }

    pub fn killed_to_team0(&self) -> bool {
        self.team_kind == TeamKind::NonTeam0 && !self.is_locked()
    }

    pub fn team_kind(&self) -> TeamKind {
        self.team_kind
    }

    /// unlock team for the unlock team tile
    pub fn unlock_team(&mut self) {
        self.locked = false;
    }

    pub fn all_finished(&self) -> bool {
        self.all_finished
    }

    pub fn can_save(&self) -> bool {
        self.team_kind != TeamKind::Team0 && self.start_time.is_some() && !self.all_finished
    }

    pub fn can_load(&self) -> bool {
        self.team_kind != TeamKind::Team0 && self.start_time.is_none()
    }

    pub fn load(&mut self, locked: bool, start_time: Option<Instant>) {
        self.locked = locked;
        self.start_time = start_time;
    }

    pub fn race_time(
        &self,
        now: Instant,
        tees: &Tees<Tee>,
        player_uid: PlayerUid,
    ) -> Option<Duration> {
        if self.team_kind() == TeamKind::NonTeam0 {
            self.start_time
                .map(|past_time| now.duration_since(past_time).unwrap())
        } else {
            let tee = tees.get_tee(player_uid).unwrap();
            tee.race_time(now)
        }
    }
}