M server/src/entity.rs => server/src/entity.rs +35 -1
@@ 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<EntityId, Entity>;
@@ 57,6 57,14 @@ impl EntityHandler {
}
players
}
+ pub fn get_player_from_id(&self, id: EntityId) -> Option<Player> {
+ 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<EntityId> {
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<Module> {
+ 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<EntityId> {
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<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_attached_from_id(&self, id: EntityId) -> Option<AttachedModule> {
+ 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),
}
M server/src/handler.rs => server/src/handler.rs +16 -5
@@ 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<RwLock<EntityHandle
collider_set.insert_with_parent(player_collider, player_handle, &mut rigid_body_set);
- data_handle.rigid_body_set = rigid_body_set;
- data_handle.collider_set = collider_set;
let mut player = Player {
handle: player_handle,
input: Default::default(),
addr: remote_addr,
auth_token: None,
- auth_user: None
+ auth_user: None,
+ children: [None, None, None, None],
};
let mut e_write_handle = entities.write().await;
@@ 198,7 198,18 @@ pub async fn handle_client(mgr: ClientManager, entities: Arc<RwLock<EntityHandle
player.load_api_data(&player_data);
}
- e_write_handle.entities.insert(get_entity_id(), Entity::Player(player));
+ let player_id = get_entity_id();
+ e_write_handle.entities.insert(player_id, Entity::Player(player));
+ AttachedModule::attach_new(&mut data_handle, &mut e_write_handle,
+ player_id, player_id,
+ ModuleTemplate {
+ translation: vector![0.0, 50.0],
+ heading: 0.0,
+ mass_properties: MassProperties::new(point![0.0, 0.0], 120.0, 122500.0),
+ module_type: ModuleType::Cargo,
+ }, 0, angle);
+ data_handle.rigid_body_set = rigid_body_set;
+ data_handle.collider_set = collider_set;
debug!("running");
}
},
M server/src/manager.rs => server/src/manager.rs +196 -2
@@ 1,13 1,18 @@
use std::collections::HashMap;
+use std::f64::consts::PI;
use std::net::SocketAddr;
use std::sync::Arc;
+use nalgebra::point;
use rapier2d_f64::na::Vector2;
-use rapier2d_f64::prelude::{IntegrationParameters, PhysicsPipeline, IslandManager, BroadPhase, NarrowPhase, ImpulseJointSet, MultibodyJointSet, CCDSolver, RigidBodySet, ColliderSet, RigidBodyHandle};
+use rapier2d_f64::prelude::{IntegrationParameters, PhysicsPipeline, IslandManager, BroadPhase, NarrowPhase, ImpulseJointSet, MultibodyJointSet, CCDSolver, RigidBodySet, ColliderSet, RigidBodyHandle, ImpulseJointHandle, RigidBodyBuilder, ColliderBuilder, FixedJointBuilder, Real, MassProperties, Isometry};
use async_std::sync::RwLock;
use async_std::channel::Sender;
use starkingdoms_protocol::api::APISavedPlayerData;
use starkingdoms_protocol::module::ModuleType;
+use crate::SCALE;
+use crate::entity::{EntityId, EntityHandler, Entity, get_entity_id};
+
#[derive(Clone)]
pub struct ClientManager {
pub handlers: Arc<RwLock<HashMap<SocketAddr, ClientHandler>>>,
@@ 21,6 26,7 @@ pub struct Player {
pub addr: SocketAddr,
pub auth_token: Option<String>,
pub auth_user: Option<String>,
+ pub children: [Option<Attachment>; 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<AttachedModule> {
+ 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<Real>,
+ 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<Attachment>; 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<AttachedModule> {
+ 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,
M server/src/timer.rs => server/src/timer.rs +17 -3
@@ 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<RwLock<Physic
warn!("unable to send position packet: {}", e);
}
};
- let modules = entities.read().await.get_modules();
+ let mut modules = entities.read().await.get_modules();
+ let attached_modules = entities.read().await.get_all_attached();
+ let attached_handles: Vec<RigidBodyHandle> = 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<starkingdoms_protocol::module::Module> = modules.iter()
.map(|module| {
let body = physics_data.rigid_body_set.get(module.handle).unwrap();