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<EntityId, Entity>;
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<Planet> {
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<Planet> {
self.get_planets().iter().find(|u| u.planet_type == planet_type).cloned()
}
pub fn get_planet_id(&self, planet_type: PlanetType) -> Option<EntityId> {
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<Player> {
if let Some(Entity::Player(player)) = self.entities.get(&id) {
Some(player.clone())
} else {
None
}
}
pub fn get_player_id(&self, addr: SocketAddr) -> Option<EntityId> {
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<Player> {
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<Module> {
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<Module> {
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<EntityId> {
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<AttachedModule> {
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<AttachedModule> {
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<EntityId> {
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),
}