use crate::ids::PlayerUid;
use crate::state::{GameState, Tees};
use crate::SnapOuter;
use std::cmp::Ordering;
use std::fmt::Debug;
use tee::Tee;
use twgame_core::twsnap::time::Instant;
use twgame_core::twsnap::Snap;
pub mod tee;
mod laser;
mod pickup;
mod projectile;
use crate::state::SpawnMode;
pub use laser::Laser;
pub use pickup::Pickup;
pub use projectile::Projectile;
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum SpawnOrderEntity {
Tee(SpawnMode),
Projectile,
}
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub struct SpawnOrder {
player_uid: PlayerUid,
tick: Instant,
entity: SpawnOrderEntity,
}
impl SpawnOrder {
pub fn new(player_uid: PlayerUid, tick: Instant, entity: SpawnOrderEntity) -> Self {
Self {
player_uid,
tick,
entity,
}
}
}
impl Ord for SpawnOrder {
fn cmp(&self, other: &Self) -> Ordering {
match self.tick.cmp(&other.tick) {
Ordering::Less => return Ordering::Less,
Ordering::Greater => return Ordering::Greater,
Ordering::Equal => {}
}
match (self.entity, other.entity) {
(SpawnOrderEntity::Tee(weak1), SpawnOrderEntity::Tee(weak2)) if weak1 == weak2 => {
self.player_uid.cmp(&other.player_uid)
}
(SpawnOrderEntity::Tee(_), SpawnOrderEntity::Tee(SpawnMode::Normal)) => {
Ordering::Greater
}
(SpawnOrderEntity::Tee(_), SpawnOrderEntity::Tee(_)) => Ordering::Less,
(SpawnOrderEntity::Tee(_), SpawnOrderEntity::Projectile) => Ordering::Greater,
(SpawnOrderEntity::Projectile, SpawnOrderEntity::Tee(_)) => Ordering::Less,
(SpawnOrderEntity::Projectile, SpawnOrderEntity::Projectile) => {
Ordering::Equal
}
}
}
}
impl PartialOrd for SpawnOrder {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
pub trait MapEntity {
fn tick(&mut self, now: Instant, game_state: &mut GameState, tees: &mut Tees<Tee>);
fn snap(&self, snapshot: &mut Snap);
}
pub trait SpawnableEntity {
fn tick(&mut self, now: Instant, game_state: &mut GameState, snap_outer: &mut SnapOuter);
fn snap(&self, now: Instant, game_state: &GameState, snapshot: &mut Snap);
fn is_marked_for_destroy(&self) -> bool;
fn spawn_order(&self) -> SpawnOrder;
fn player_uid(&self) -> PlayerUid;
fn on_tee_swap(&mut self, pid1: PlayerUid, pid2: PlayerUid);
}
#[derive(Debug, Clone)]
pub enum MapEntityItem {
Pickup(Pickup),
}
impl MapEntityItem {
pub fn pickup(pickup: Pickup) -> Self {
Self::Pickup(pickup)
}
}
impl MapEntity for MapEntityItem {
fn tick(&mut self, now: Instant, game_state: &mut GameState, tees: &mut Tees<Tee>) {
match self {
Self::Pickup(pickup) => pickup.tick(now, game_state, tees),
}
}
fn snap(&self, snapshot: &mut Snap) {
match self {
Self::Pickup(pickup) => pickup.snap(snapshot),
}
}
}
#[derive(Debug)]
pub(crate) enum EntityItem {
Tee(PlayerUid),
Projectile(Projectile),
Laser(Laser),
}
#[derive(Debug)]
pub enum EntityItemNew {
Projectile(Projectile),
Laser(Laser),
}
impl EntityItemNew {
pub fn projectile(projectile: Projectile) -> Self {
Self::Projectile(projectile)
}
pub fn laser(laser: Laser) -> Self {
Self::Laser(laser)
}
}
impl EntityItem {
pub(crate) fn tick(
&mut self,
now: Instant,
game_state: &mut GameState,
tees: &mut Tees<Tee>,
snap_outer: &mut SnapOuter,
) {
match self {
Self::Tee(tee_uid) => tees
.get_tee_mut(*tee_uid)
.unwrap()
.tick(now, game_state, snap_outer),
Self::Projectile(projectile) => projectile.tick(now, game_state, snap_outer),
Self::Laser(laser) => laser.tick(now, game_state, snap_outer),
}
}
pub(crate) fn snap(
&self,
now: Instant,
game_state: &GameState,
snapshot: &mut Snap,
tees: &Tees<Tee>,
) {
match self {
Self::Tee(tee_uid) => tees
.get_tee(*tee_uid)
.unwrap()
.snap(now, game_state, snapshot),
Self::Projectile(projectile) => projectile.snap(now, game_state, snapshot),
Self::Laser(laser) => laser.snap(now, game_state, snapshot),
}
}
pub(crate) fn is_marked_for_destroy(&self, tees: &Tees<Tee>) -> bool {
match self {
Self::Tee(tee) => tees.get_tee(*tee).unwrap().is_marked_for_destroy(),
Self::Projectile(projectile) => projectile.is_marked_for_destroy(),
Self::Laser(laser) => laser.is_marked_for_destroy(),
}
}
pub(crate) fn spawn_order(&self, tees: &Tees<Tee>) -> SpawnOrder {
match self {
Self::Tee(tee) => tees.get_tee(*tee).unwrap().spawn_order(),
Self::Projectile(projectile) => projectile.spawn_order(),
Self::Laser(laser) => laser.spawn_order(),
}
}
pub(crate) fn player_uid(&self) -> PlayerUid {
match self {
Self::Tee(tee) => *tee,
Self::Projectile(projectile) => projectile.player_uid(),
Self::Laser(laser) => laser.player_uid(),
}
}
pub(crate) fn on_tee_swap(&mut self, tees: &mut Tees<Tee>, pid1: PlayerUid, pid2: PlayerUid) {
match self {
Self::Tee(tee) => tees.get_tee_mut(*tee).unwrap().on_tee_swap(pid1, pid2),
Self::Laser(laser) => laser.on_tee_swap(pid1, pid2),
Self::Projectile(projectile) => projectile.on_tee_swap(pid1, pid2),
}
}
}