use std::{collections::HashMap, net::SocketAddr, sync::atomic::AtomicU32}; use nalgebra::Vector2; use protobuf::SpecialFields; use starkingdoms_protocol::planet::PlanetType; use crate::{ manager::{ClientHandlerMessage, Player}, module::{AttachedModule, Module}, planet::Planet, SCALE, }; pub type EntityId = u32; pub type Entities = HashMap; static mut ENTITY_ID_COUNT: AtomicU32 = AtomicU32::new(0); pub fn get_entity_id() -> EntityId { let last_entity_id = unsafe { &ENTITY_ID_COUNT }; let id = last_entity_id.fetch_add(1, std::sync::atomic::Ordering::AcqRel); assert!(id <= 4_147_483_600, "No remaining entity ids"); id } #[derive(Default)] pub struct EntityHandler { pub entities: Entities, } impl EntityHandler { pub fn new() -> Self { Self { entities: Entities::new(), } } pub fn get_planets(&self) -> Vec { let mut ids = Vec::new(); for entity in self.entities.values() { if let Entity::Planet(planet) = entity { ids.push(planet.clone()); } } ids } pub fn get_planet(&self, planet_type: PlanetType) -> Option { self.get_planets().iter().find(|u| u.planet_type == planet_type).cloned() } pub fn get_planet_id(&self, planet_type: PlanetType) -> Option { for (id, entity) in &self.entities { if let Entity::Planet(planet) = entity { if planet.planet_type == planet_type { return Some(*id); } } } None } pub fn get_players(&self) -> Vec<(SocketAddr, Player)> { let mut players = Vec::new(); for entity in self.entities.values() { if let Entity::Player(player) = entity { players.push((player.addr, player.clone())); } } players } pub fn get_player_from_id(&self, id: EntityId) -> Option { if let Some(Entity::Player(player)) = self.entities.get(&id) { Some(player.clone()) } else { None } } pub fn get_player_id(&self, addr: SocketAddr) -> Option { for (id, entity) in &self.entities { if let Entity::Player(player) = entity { if player.addr == addr { return Some(*id); } } } None } pub fn get_player(&self, addr: SocketAddr) -> Option { let players = self.get_players(); let player = players.iter().find(|p| p.0 == addr); player.map(|p| p.1.clone()) } pub fn get_modules(&self) -> Vec { let mut modules = Vec::new(); for entity in self.entities.values() { if let Entity::Module(module) = entity { modules.push(module.clone()); } } modules } pub fn get_modules_id(&self) -> Vec<(EntityId, Module)> { let mut modules = Vec::new(); for (id, entity) in self.entities.clone() { if let Entity::Module(module) = entity { modules.push((id, module.clone())); } } modules } pub fn get_module_count(&self) -> u32 { let mut module_count = 0; for entity in self.entities.values() { if let Entity::Module(_module) = entity { module_count += 1; } } module_count } pub fn get_module_from_id(&self, id: EntityId) -> Option { if let Some(Entity::Module(module)) = self.entities.get(&id) { return Some(module.clone()); } None } pub fn get_from_module(&self, p_module: &Module) -> Option { for (id, entity) in &self.entities { if let Entity::Module(module) = entity { if module.handle == p_module.handle { return Some(*id); } } } None } pub fn get_all_attached(&self) -> Vec { let mut modules = Vec::new(); for entity in self.entities.values() { if let Entity::AttachedModule(module) = entity { modules.push(module.clone()); } } modules } pub fn get_all_attached_id(&self) -> Vec<(EntityId, AttachedModule)> { let mut modules = Vec::new(); for (id, entity) in self.entities.clone() { if let Entity::AttachedModule(module) = entity { modules.push((id, module.clone())); } } modules } pub fn get_attached_from_id(&self, id: EntityId) -> Option { if let Some(Entity::AttachedModule(module)) = self.entities.get(&id) { return Some(module.clone()); } None } pub fn get_id_from_attached(&self, p_module: &AttachedModule) -> Option { for (id, entity) in &self.entities { if let Entity::AttachedModule(module) = entity { if module.handle == p_module.handle { return Some(*id); } } } None } pub fn gravity(&self, position: (f64, f64), mass: f64) -> (f64, f64) { let mut direction = Vector2::zeros(); let planets = self.get_planets(); for planet in planets { let planet_grav = planet.gravity(position, mass); direction.x += planet_grav.0; direction.y += planet_grav.1; } (direction.x, direction.y) } pub fn to_protocol(&self) -> ClientHandlerMessage { let mut planets = vec![]; for planet in self.get_planets() { planets.push(starkingdoms_protocol::planet::Planet { planet_type: planet.planet_type.into(), x: planet.position.0 * SCALE, y: planet.position.1 * SCALE, radius: planet.radius * SCALE, // DO NOT * SCALE. THIS VALUE IS NOT SCALED! YES IT IS special_fields: SpecialFields::default(), }); } ClientHandlerMessage::PlanetData { planets } } } #[derive(Clone, Debug)] pub enum Entity { Player(Player), Planet(Planet), Module(Module), AttachedModule(AttachedModule), }