~starkingdoms/starkingdoms

aaa46071f791e2735f9d8b1f7b546b755c00a806 — ghostlyzsh 2 years ago 61990a8
attachment technically works, but not really
4 files changed, 264 insertions(+), 11 deletions(-)

M server/src/entity.rs
M server/src/handler.rs
M server/src/manager.rs
M server/src/timer.rs
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();