From aaa46071f791e2735f9d8b1f7b546b755c00a806 Mon Sep 17 00:00:00 2001 From: ghostlyzsh Date: Sun, 23 Apr 2023 17:00:47 -0500 Subject: [PATCH] attachment technically works, but not really --- server/src/entity.rs | 36 +++++++- server/src/handler.rs | 21 +++-- server/src/manager.rs | 198 +++++++++++++++++++++++++++++++++++++++++- server/src/timer.rs | 20 ++++- 4 files changed, 264 insertions(+), 11 deletions(-) diff --git a/server/src/entity.rs b/server/src/entity.rs index 1d7d80aa339daa2ae032f464889a5596fc6b5f35..2ed4f9ef9b08f01e584f08ee516fa1714a0b72c5 100644 --- a/server/src/entity.rs +++ b/server/src/entity.rs @@ -3,7 +3,7 @@ use std::{sync::atomic::AtomicU32, collections::HashMap, net::SocketAddr}; use nalgebra::Vector2; use starkingdoms_protocol::planet::PlanetType; -use crate::{planet::Planet, SCALE, manager::{ClientHandlerMessage, Player, Module}}; +use crate::{planet::Planet, SCALE, manager::{ClientHandlerMessage, Player, Module, AttachedModule}}; pub type EntityId = u32; pub type Entities = HashMap; @@ -57,6 +57,14 @@ impl EntityHandler { } players } + pub fn get_player_from_id(&self, id: EntityId) -> Option { + if let Some(entity) = self.entities.get(&id) { + if let Entity::Player(player) = entity { + return Some(player.clone()); + } + } + None + } pub fn get_player_id(&self, addr: SocketAddr) -> Option { for (id, entity) in self.entities.iter() { if let Entity::Player(player) = entity { @@ -97,6 +105,14 @@ impl EntityHandler { } module_count } + pub fn get_module_from_id(&self, id: EntityId) -> Option { + if let Some(entity) = self.entities.get(&id) { + if let Entity::Module(module) = entity { + return Some(module.clone()); + } + } + None + } pub fn get_from_module(&self, p_module: &Module) -> Option { for (id, entity) in self.entities.iter() { if let Entity::Module(module) = entity { @@ -107,6 +123,23 @@ impl EntityHandler { } 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_attached_from_id(&self, id: EntityId) -> Option { + if let Some(entity) = self.entities.get(&id) { + if let Entity::AttachedModule(module) = entity { + return Some(module.clone()); + } + } + None + } pub fn gravity(&self, position: (f64, f64), mass: f64) -> (f64, f64) { let mut direction = Vector2::zeros(); @@ -144,4 +177,5 @@ pub enum Entity { Player(Player), Planet(Planet), Module(Module), + AttachedModule(AttachedModule), } diff --git a/server/src/handler.rs b/server/src/handler.rs index b9778d39bf32edd113f1e76be1f7baf85573bdaa..72790c4e22c8ab9eb9f871ffa3d96b1f787a6b65 100644 --- a/server/src/handler.rs +++ b/server/src/handler.rs @@ -9,13 +9,14 @@ use log::{error, info, debug, warn}; use nalgebra::{vector, point}; use rand::Rng; use rapier2d_f64::prelude::{RigidBodyBuilder, RigidBodyType, ColliderBuilder, MassProperties, Collider}; +use starkingdoms_protocol::module::ModuleType; use tungstenite::Message; use starkingdoms_protocol::goodbye_reason::GoodbyeReason; use starkingdoms_protocol::message_s2c::{MessageS2CChat, MessageS2CGoodbye, MessageS2CHello, MessageS2CPlanetData, MessageS2CPlayersUpdate, MessageS2CPong, MessageS2CModulesUpdate}; use starkingdoms_protocol::{MessageS2C, MessageC2S, PROTOCOL_VERSION}; use starkingdoms_protocol::state::State; use crate::entity::{EntityHandler, get_entity_id, Entity}; -use crate::manager::{ClientHandlerMessage, ClientManager, PhysicsData, Player}; +use crate::manager::{ClientHandlerMessage, ClientManager, PhysicsData, Player, AttachedModule, ModuleTemplate}; use crate::{send, recv, SCALE}; use async_std::{sync::RwLock, channel::Receiver}; use async_std::net::TcpStream; @@ -166,15 +167,14 @@ pub async fn handle_client(mgr: ClientManager, entities: Arc>>, @@ -21,6 +26,7 @@ pub struct Player { pub addr: SocketAddr, pub auth_token: Option, pub auth_user: Option, + pub children: [Option; 4], } impl Player { @@ -31,15 +37,203 @@ impl Player { pub fn load_api_data(&mut self, _data: &APISavedPlayerData) { } + pub fn search_modules(&self, entities: &EntityHandler) -> Vec { + let mut modules = Vec::new(); + for child in &self.children { + if let Some(attachment) = child { + if let Entity::AttachedModule(child_module) = entities.entities.get(&attachment.child).unwrap() { + modules.append(&mut child_module.search_modules(entities)); + } + } + } + modules + } } -#[derive(Clone)] +#[derive(Debug, Clone)] pub struct Module { pub handle: RigidBodyHandle, pub module_type: ModuleType, pub lifetime: f64, } +#[derive(Clone)] +pub struct ModuleTemplate { + pub translation: Vector2, + pub heading: f64, + pub mass_properties: MassProperties, + pub module_type: ModuleType, +} + +#[derive(Debug, Clone)] +pub struct AttachedModule { + pub handle: RigidBodyHandle, + pub module_type: ModuleType, + pub player_id: EntityId, + pub children: [Option; 4], +} +impl AttachedModule { + pub fn attach(data: &mut PhysicsData, entities: &mut EntityHandler, parent: EntityId, + player_id: EntityId, module: Module, attachment_slot: usize) { + let mut entity_map = entities.entities.clone(); + + let loose_id = entities.get_from_module(&module).expect("loose module does not exist"); + let loose_body = data.rigid_body_set.get(module.handle).expect("loose module does not exist"); + let mut parent_entity = entity_map.get_mut(&parent).expect("parent id does not exist"); + let parent_handle = match parent_entity { + Entity::Player(player) => { + player.handle + }, + Entity::AttachedModule(module) => { + module.handle + }, + _ => { + panic!("unexpected parent"); + } + }; + let parent_body = data.rigid_body_set + .get(parent_handle).unwrap(); + // create attachment module + let module_collider = ColliderBuilder::cuboid(25.0 / SCALE, 25.0 / SCALE) + .mass_properties(loose_body.mass_properties().local_mprops) + .build(); + let module_body = RigidBodyBuilder::dynamic() + .translation(*loose_body.translation()) + .rotation(loose_body.rotation().angle()) + .build(); + let attached_handle = data.rigid_body_set.insert(module_body); + data.collider_set.insert_with_parent(module_collider, attached_handle, &mut data.rigid_body_set); + let attach_joint = FixedJointBuilder::new() + .local_anchor1(point![0.0, 0.0]) + .local_anchor2(point![0.0, 0.0]) + .build(); + let attach_joint_handle = data.impulse_joint_set.insert(parent_handle, attached_handle, attach_joint, true); + let attached_module = AttachedModule { + handle: attached_handle, + module_type: module.module_type, + player_id, + children: [None, None, None, None], + }; + let attached_id = get_entity_id(); + match parent_entity { + Entity::Player(ref mut player) => { + player.children[attachment_slot] = Some(Attachment { + child: attached_id, + connection: attach_joint_handle, + }); + }, + Entity::AttachedModule(ref mut module) => { + module.children[attachment_slot] = Some(Attachment { + child: attached_id, + connection: attach_joint_handle, + }); + }, + _ => { + panic!("unexpected parent"); + } + }; + entity_map.insert(attached_id, Entity::AttachedModule(attached_module)); + // delete loose module + data.rigid_body_set.remove(module.handle, + &mut data.island_manager, + &mut data.collider_set, + &mut data.impulse_joint_set, + &mut data.multibody_joint_set, true); + entities.entities.remove(&loose_id); + } + pub fn attach_new(data: &mut PhysicsData, entities: &mut EntityHandler, parent: EntityId, + player_id: EntityId, module: ModuleTemplate, attachment_slot: usize, rotation: f64) { + let mut entity_map = entities.entities.clone(); + + //let loose_id = entities.get_from_module(&module).expect("loose module does not exist"); + //let loose_body = data.rigid_body_set.get(module.handle).expect("loose module does not exist"); + let mut parent_entity = entity_map.get_mut(&parent).expect("parent id does not exist"); + let parent_handle = match parent_entity { + Entity::Player(player) => { + player.handle + }, + Entity::AttachedModule(module) => { + module.handle + }, + _ => { + panic!("unexpected parent"); + } + }; + // create attachment module + let module_collider = ColliderBuilder::cuboid(25.0 / SCALE, 25.0 / SCALE) + .mass_properties(module.mass_properties) + .build(); + let module_body = RigidBodyBuilder::dynamic() + .translation(module.translation) + .rotation(module.heading) + .build(); + let attached_handle = data.rigid_body_set.insert(module_body); + data.collider_set.insert_with_parent(module_collider, attached_handle, &mut data.rigid_body_set); + let anchor = point![ + -0. / SCALE * rotation.cos() +100. / SCALE * rotation.sin(), + -0. / SCALE * rotation.sin() -100. / SCALE * rotation.cos() + ]; + let attach_joint = FixedJointBuilder::new() + .local_anchor1(anchor) + .local_anchor2(point![0.0, 0.0 / SCALE]) + .local_frame2(Isometry::rotation(rotation)) + .build(); + let attach_joint_handle = data.impulse_joint_set.insert(parent_handle, attached_handle, attach_joint, true); + let attached_module = AttachedModule { + handle: attached_handle, + module_type: module.module_type, + player_id, + children: [None, None, None, None], + }; + let attached_id = get_entity_id(); + match parent_entity { + Entity::Player(ref mut player) => { + player.children[attachment_slot] = Some(Attachment { + child: attached_id, + connection: attach_joint_handle, + }); + }, + Entity::AttachedModule(ref mut module) => { + module.children[attachment_slot] = Some(Attachment { + child: attached_id, + connection: attach_joint_handle, + }); + }, + _ => { + panic!("unexpected parent"); + } + }; + entity_map.insert(attached_id, Entity::AttachedModule(attached_module)); + entities.entities = entity_map; + } + // TODO: remove this function + pub fn to_module(&self) -> Module { + Module { + handle: self.handle, + module_type: self.module_type, + lifetime: 10., + } + } + pub fn search_modules(&self, entities: &EntityHandler) -> Vec { + let mut modules = Vec::new(); + for child in &self.children { + if let Some(attachment) = child { + let child_module = entities.entities.get(&attachment.child).unwrap(); + if let Entity::AttachedModule(child_module) = entities.entities.get(&attachment.child).unwrap() { + modules.append(&mut child_module.search_modules(entities)); + } + } + } + modules + } +} + +#[derive(Debug, Clone)] +pub struct Attachment { + pub child: EntityId, + pub connection: ImpulseJointHandle, +} + #[derive(Default, Clone)] pub struct PlayerInput { pub up: bool, diff --git a/server/src/timer.rs b/server/src/timer.rs index 1e87a7d84133207be73de2ea9e73b8413ee633a8..3857917523aafc1887f28adee2d3d38bda67fcb2 100644 --- a/server/src/timer.rs +++ b/server/src/timer.rs @@ -1,8 +1,8 @@ use std::{time::Duration, sync::Arc, f64::consts::PI}; -use log::{debug, warn}; +use log::{debug, warn, info}; use nalgebra::{vector, point}; use rand::Rng; -use rapier2d_f64::prelude::{PhysicsPipeline, ColliderBuilder, RigidBodyBuilder, MassProperties}; +use rapier2d_f64::prelude::{PhysicsPipeline, ColliderBuilder, RigidBodyBuilder, MassProperties, RigidBodyHandle}; use async_std::sync::RwLock; use async_std::task::sleep; use starkingdoms_protocol::{player::Player, planet::PlanetType, module::ModuleType}; @@ -245,7 +245,21 @@ pub async fn timer_main(mgr: ClientManager, physics_data_orig: Arc = attached_modules.iter().map(|m| { + m.handle + }).collect(); + modules.append(&mut attached_modules.iter().map(|m| { + let module = m.to_module(); + info!("{:?}", module); + return module; + }).collect()); + modules.iter().for_each(|module| { + if attached_handles.contains(&module.handle) { + info!("{:?}", physics_data.rigid_body_set.get(module.handle).unwrap().translation()); + } + }); let protocol_modules: Vec = modules.iter() .map(|module| { let body = physics_data.rigid_body_set.get(module.handle).unwrap();