use slotmap::{new_key_type, Key, KeyData};
use twgame_core::twsnap::SnapId;
use vek::num_integer::Integer;
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct TeamId {
id: i32,
}
impl TeamId {
pub fn from_i32(id: i32) -> Self {
Self { id }
}
pub fn team0() -> Self {
Self { id: 0 }
}
pub fn is_team0(&self) -> bool {
self.id == 0
}
pub fn to_i32(self) -> i32 {
self.id
}
}
new_key_type! { pub struct PlayerUid; }
#[derive(Debug, Default)]
pub struct PlayerUidGenerator {
players: Vec<u32>,
}
impl PlayerUidGenerator {
pub fn player_join(&mut self, idx: u32) -> PlayerUid {
if idx as usize >= self.players.len() {
self.players.resize(idx as usize + 1, 0);
}
let version = self.players.get_mut(idx as usize).unwrap();
assert!(
version.is_even(),
"player_join called for already existing player"
);
*version += 1;
PlayerUid::from_idx_version(idx, *version)
}
pub fn player_leave(&mut self, idx: u32) -> PlayerUid {
let version = self
.players
.get_mut(idx as usize)
.expect("player_leave called for non-existing player");
assert!(
version.is_odd(),
"player_leave called for non-existing player"
);
let pid = PlayerUid::from_idx_version(idx, *version);
*version += 1;
pid
}
pub fn get(&self, idx: u32) -> Option<PlayerUid> {
let version = self.players.get(idx as usize)?;
if version.is_even() {
return None;
}
Some(PlayerUid::from_idx_version(idx, *version))
}
}
impl PlayerUid {
pub fn snap_id(&self) -> SnapId {
let id = self.data().as_ffi() & 0xffff_ffff;
SnapId((id as u32).checked_sub(1).unwrap())
}
fn from_idx_version(idx: u32, version: u32) -> Self {
let key = (u64::from(version) << 32) | u64::from(idx + 1);
let mut this = Self::null();
this.0 = KeyData::from_ffi(key);
this
}
}
#[derive(Debug, Clone)]
pub struct MapSnapIdGenerator {
next_projectile_id: u16,
next_laser_id: u16,
next_pickup_id: u16,
}
impl Default for MapSnapIdGenerator {
fn default() -> Self {
Self::new()
}
}
impl MapSnapIdGenerator {
pub fn new() -> Self {
Self {
next_projectile_id: 0,
next_laser_id: 0,
next_pickup_id: 0,
}
}
pub fn finalize(self) -> SnapIdGenerator {
SnapIdGenerator {
num_map_projectile: self.next_projectile_id,
next_projectile_id: self.next_projectile_id,
num_map_laser: self.next_laser_id,
next_laser_id: self.next_laser_id,
}
}
pub fn next_projectile(&mut self) -> SnapId {
let snap_id = SnapId(self.next_projectile_id as u32);
self.next_projectile_id = self
.next_projectile_id
.checked_add(1)
.expect("too many map projectiles");
snap_id
}
pub fn next_laser(&mut self) -> SnapId {
let snap_id = SnapId(self.next_laser_id as u32);
self.next_laser_id = self
.next_laser_id
.checked_add(1)
.expect("too many map laser");
snap_id
}
pub fn next_pickup(&mut self) -> SnapId {
let snap_id = SnapId(self.next_pickup_id as u32);
self.next_pickup_id = self
.next_pickup_id
.checked_add(1)
.expect("too many map pickups");
snap_id
}
}
#[derive(Debug)]
pub struct SnapIdGenerator {
num_map_projectile: u16,
next_projectile_id: u16,
num_map_laser: u16,
next_laser_id: u16,
}
impl SnapIdGenerator {
pub fn next_projectile(&mut self) -> SnapId {
let snap_id = SnapId(self.next_projectile_id as u32);
self.next_projectile_id = self
.next_projectile_id
.checked_add(1)
.unwrap_or(self.num_map_projectile);
snap_id
}
pub fn next_laser(&mut self) -> SnapId {
let snap_id = SnapId(self.next_laser_id as u32);
self.next_laser_id = self
.next_laser_id
.checked_add(1)
.unwrap_or(self.num_map_laser);
snap_id
}
}