~starkingdoms/starkingdoms

600a7f831def6a73e0651c6cd14390cb463f4a8a — core 2 years ago 29a5457
code cleanup pt2
M server/src/handler.rs => server/src/handler.rs +72 -69
@@ 1,6 1,6 @@
use crate::api::{load_player_data_from_api, save_player_data_to_api};
use crate::entity::{get_entity_id, Entity, EntityHandler};
use crate::manager::{ClientHandlerMessage, ClientManager, PhysicsData, Player};
use crate::manager::{ClientHandlerMessage, ClientManager, PhysicsData, Player, PlayerInput};
use crate::module::{AttachedModule, Module};
use crate::{recv, send, SCALE};
use async_std::net::TcpStream;


@@ 21,6 21,7 @@ use starkingdoms_protocol::message_s2c::{
    MessageS2CPlanetData, MessageS2CPlayersUpdate, MessageS2CPong,
};

use protobuf::SpecialFields;
use starkingdoms_protocol::state::State;
use starkingdoms_protocol::{MessageC2S, MessageS2C, PROTOCOL_VERSION};
use std::error::Error;


@@ 28,7 29,6 @@ use std::f64::consts::PI;
use std::net::SocketAddr;
use std::sync::Arc;
use std::time::{Duration, SystemTime};
use protobuf::SpecialFields;
use tungstenite::Message;

pub async fn handle_client(


@@ 53,7 53,7 @@ pub async fn handle_client(
                        let msg = MessageS2C::Chat(MessageS2CChat {
                            from,
                            message,
                            special_fields: Default::default(),
                            special_fields: SpecialFields::default(),
                        })
                        .try_into()?;
                        send!(client_tx, msg).await?;


@@ 63,7 63,7 @@ pub async fn handle_client(
                    if matches!(state, State::Play) {
                        let msg = MessageS2C::PlayersUpdate(MessageS2CPlayersUpdate {
                            players,
                            special_fields: Default::default(),
                            special_fields: SpecialFields::default(),
                        })
                        .try_into()?;
                        send!(client_tx, msg).await?;


@@ 73,7 73,7 @@ pub async fn handle_client(
                    if matches!(state, State::Play) {
                        let msg = MessageS2C::PlanetData(MessageS2CPlanetData {
                            planets,
                            special_fields: Default::default(),
                            special_fields: SpecialFields::default(),
                        })
                        .try_into()?;
                        send!(client_tx, msg).await?;


@@ 83,7 83,7 @@ pub async fn handle_client(
                    if matches!(state, State::Play) {
                        let msg = MessageS2C::ModulesUpdate(MessageS2CModulesUpdate {
                            modules,
                            special_fields: Default::default(),
                            special_fields: SpecialFields::default(),
                        })
                        .try_into()?;
                        send!(client_tx, msg).await?;


@@ 93,7 93,7 @@ pub async fn handle_client(
                    if matches!(state, State::Play) {
                        let msg = MessageS2C::ModuleTreeUpdate(MessageS2CModuleTreeUpdate {
                            tree: modules,
                            special_fields: Default::default(),
                            special_fields: SpecialFields::default(),
                        })
                        .try_into()?;
                        send!(client_tx, msg).await?;


@@ 109,7 109,7 @@ pub async fn handle_client(
            error!("[{}] ping timeout", remote_addr);
            let msg = MessageS2C::Goodbye(MessageS2CGoodbye {
                reason: GoodbyeReason::PingPongTimeout.into(),
                special_fields: Default::default(),
                special_fields: SpecialFields::default(),
            })
            .try_into()?;
            send!(client_tx, msg).await?;


@@ 147,7 147,7 @@ pub async fn handle_client(
                                );
                                let msg = MessageS2C::Goodbye(MessageS2CGoodbye {
                                    reason: GoodbyeReason::UnsupportedProtocol.into(),
                                    special_fields: Default::default(),
                                    special_fields: SpecialFields::default(),
                                })
                                .try_into()?;
                                send!(client_tx, msg).await?;


@@ 169,7 169,7 @@ pub async fn handle_client(
                                    );
                                    let msg: Vec<u8> = MessageS2C::Goodbye(MessageS2CGoodbye {
                                        reason: GoodbyeReason::UsernameTaken.into(),
                                        special_fields: Default::default(),
                                        special_fields: SpecialFields::default(),
                                    })
                                    .try_into()?;
                                    send!(client_tx, msg).await?;


@@ 234,7 234,7 @@ pub async fn handle_client(

                                let mut player = Player {
                                    handle: player_handle,
                                    input: Default::default(),
                                    input: PlayerInput::default(),
                                    addr: remote_addr,
                                    auth_token: None,
                                    auth_user: None,


@@ 286,39 286,6 @@ pub async fn handle_client(

                                data_handle.rigid_body_set = rigid_body_set;
                                data_handle.collider_set = collider_set;

                                /*let module_id = AttachedModule::attach_new(
                                    &mut data_handle,
                                    &mut e_write_handle,
                                    player_id,
                                    player_id,
                                    ModuleTemplate {
                                        translation: vector![0.0, 50.0],
                                        mass_properties: MassProperties::new(
                                            point![0.0, 0.0],
                                            0.0001,
                                            0.005,
                                        ),
                                        module_type: ModuleType::Cargo,
                                    },
                                    1,
                                );
                                let module_id = AttachedModule::attach_new(
                                    &mut data_handle,
                                    &mut e_write_handle,
                                    module_id,
                                    player_id,
                                    ModuleTemplate {
                                        translation: vector![0.0, 50.0],
                                        mass_properties: MassProperties::new(
                                            point![0.0, 0.0],
                                            0.0001,
                                            0.005,
                                        ),
                                        module_type: ModuleType::Cargo,
                                    },
                                    2,
                                );*/
                            }
                        }
                        MessageC2S::Goodbye(pkt) => {


@@ 361,7 328,10 @@ pub async fn handle_client(
                    MessageC2S::Chat(pkt) => {
                        info!("[{}] CHAT: [{}] {}", remote_addr, username, pkt.message);

                        for (_addr, client_thread) in mgr.handlers.read().await.iter() {
                        let read_handle = mgr.handlers.read().await;

                        #[allow(clippy::significant_drop_in_scrutinee)] // i know
                        for (_addr, client_thread) in read_handle.iter() {
                            match client_thread
                                .tx
                                .send(ClientHandlerMessage::ChatMessage {


@@ 379,12 349,14 @@ pub async fn handle_client(
                    }
                    MessageC2S::Ping(_) => {
                        let msg = MessageS2C::Pong(MessageS2CPong {
                            special_fields: Default::default(),
                            special_fields: SpecialFields::default(),
                        })
                        .try_into()?;
                        send!(client_tx, msg).await?;
                        ping_timeout = SystemTime::now() + Duration::from_secs(10);
                    }
                    #[allow(clippy::significant_drop_tightening)]
                    // TODO: Remove when this lint is developed more
                    MessageC2S::Input(p) => {
                        let mut handle = entities.write().await;
                        let id = handle


@@ 422,8 394,12 @@ pub async fn handle_client(

                        match save_player_data_to_api(
                            &player.as_api_data(),
                            &player.auth_token.ok_or("Tried to beamout without an auth token")?,
                            &player.auth_user.ok_or("Tried to beamout without setting a user")?,
                            &player
                                .auth_token
                                .ok_or("Tried to beamout without an auth token")?,
                            &player
                                .auth_user
                                .ok_or("Tried to beamout without setting a user")?,
                            &std::env::var("STK_API_KEY")?,
                        )
                        .await


@@ 432,7 408,7 @@ pub async fn handle_client(
                                info!("[{}] * Beamed out successfully", remote_addr);
                                let msg = MessageS2C::Goodbye(MessageS2CGoodbye {
                                    reason: GoodbyeReason::Done.into(),
                                    special_fields: Default::default(),
                                    special_fields: SpecialFields::default(),
                                })
                                .try_into()?;
                                send!(client_tx, msg).await?;


@@ 446,6 422,8 @@ pub async fn handle_client(
                    MessageC2S::MouseInput(_p) => {
                        //debug!("[{}] player input: {:?}", remote_addr, p);
                    }
                    #[allow(clippy::significant_drop_tightening)]
                    // TODO: Remove when this lint is developed more
                    MessageC2S::ModuleDetach(p) => {
                        let mut entities = entities.write().await;
                        let mut data_handle = data.write().await;


@@ 462,15 440,23 @@ pub async fn handle_client(
                            continue;
                        }

                        let player_id = entities.get_player_id(remote_addr).ok_or("player does not exist")?;
                        let player_id = entities
                            .get_player_id(remote_addr)
                            .ok_or("player does not exist")?;
                        let module_id = AttachedModule::detach(
                            &mut data_handle,
                            &mut entities,
                            player_id,
                            module.ok_or("cannot detach module that doesn't exist")?,
                        ).ok_or("detach failed")?;
                        let module = entities.get_module_from_id(module_id).ok_or("player does not exist")?;
                        let body = data_handle.rigid_body_set.get(module.handle).ok_or("module rigidbody does not exist")?;
                            &module.ok_or("cannot detach module that doesn't exist")?,
                        )
                        .ok_or("detach failed")?;
                        let module = entities
                            .get_module_from_id(module_id)
                            .ok_or("player does not exist")?;
                        let body = data_handle
                            .rigid_body_set
                            .get(module.handle)
                            .ok_or("module rigidbody does not exist")?;
                        let prot_module = starkingdoms_protocol::module::Module {
                            module_type: module.module_type.into(),
                            rotation: body.rotation().angle(),


@@ 498,21 484,32 @@ pub async fn handle_client(
                            //debug!("[{}] grab begin: {:?}, flags: {}", remote_addr, p, module.flags);
                        }
                    }
                    #[allow(clippy::significant_drop_tightening)]
                    // TODO: Remove when this lint is developed more
                    MessageC2S::ModuleGrabEnd(p) => {
                        let mut entities = entities.write().await;
                        let mut module: Option<Module> = None;
                        let mut did_attach = false;
                        let mut attached_id = None;
                        if let Entity::Module(p_module) =
                            entities.entities.get_mut(&p.module_id).ok_or("module does not exist")?
                        if let Entity::Module(p_module) = entities
                            .entities
                            .get_mut(&p.module_id)
                            .ok_or("module does not exist")?
                        {
                            module = Some(p_module.clone());
                            //debug!("[{}] grab end: {:?}", remote_addr, p);
                        }
                        let mut data_handle = data.write().await;
                        let player_id = entities.get_player_id(remote_addr).ok_or("player entity does not exist")?;
                        let player = entities.get_player(remote_addr).ok_or("player does not exist")?;
                        let body = data_handle.rigid_body_set.get(player.handle).ok_or("player rigidbody does not exist")?;
                        let player_id = entities
                            .get_player_id(remote_addr)
                            .ok_or("player entity does not exist")?;
                        let player = entities
                            .get_player(remote_addr)
                            .ok_or("player does not exist")?;
                        let body = data_handle
                            .rigid_body_set
                            .get(player.handle)
                            .ok_or("player rigidbody does not exist")?;
                        let (x, y) = (
                            body.translation().x - p.worldpos_x / SCALE,
                            body.translation().y - p.worldpos_y / SCALE,


@@ 528,7 525,7 @@ pub async fn handle_client(
                                &mut entities,
                                player_id,
                                player_id,
                                module.clone().ok_or("module is None")?,
                                &module.clone().ok_or("module is None")?,
                                2,
                            ));
                            did_attach = true;


@@ 538,7 535,7 @@ pub async fn handle_client(
                                &mut entities,
                                player_id,
                                player_id,
                                module.clone().ok_or("module is None")?,
                                &module.clone().ok_or("module is None")?,
                                0,
                            ));
                            did_attach = true;


@@ 548,7 545,7 @@ pub async fn handle_client(
                                &mut entities,
                                player_id,
                                player_id,
                                module.clone().ok_or("module is None")?,
                                &module.clone().ok_or("module is None")?,
                                3,
                            ));
                            did_attach = true;


@@ 558,14 555,17 @@ pub async fn handle_client(
                                &mut entities,
                                player_id,
                                player_id,
                                module.clone().ok_or("module is None")?,
                                &module.clone().ok_or("module is None")?,
                                1,
                            ));
                            did_attach = true;
                        }
                        let modules = player.search_modules(&entities);
                        for attached in modules {
                            let body = data_handle.rigid_body_set.get(attached.handle).ok_or("attached module rigidbody does not exist")?;
                            let body = data_handle
                                .rigid_body_set
                                .get(attached.handle)
                                .ok_or("attached module rigidbody does not exist")?;
                            let (x, y) = (
                                body.translation().x - p.worldpos_x / SCALE,
                                body.translation().y - p.worldpos_y / SCALE,


@@ 575,7 575,9 @@ pub async fn handle_client(
                                x.mul_add(angle.cos(), -y * angle.sin()),
                                x.mul_add(angle.sin(), y * angle.cos()),
                            );
                            let parent_id = entities.get_id_from_attached(&attached).ok_or("attached module does not exist")?;
                            let parent_id = entities
                                .get_id_from_attached(&attached)
                                .ok_or("attached module does not exist")?;

                            // ghostly: this is cursed as hell
                            // please find a better way in the future lmao


@@ 585,7 587,7 @@ pub async fn handle_client(
                                    &mut entities,
                                    parent_id,
                                    player_id,
                                    module.clone().ok_or("module does not exist")?,
                                    &module.clone().ok_or("module does not exist")?,
                                    2,
                                ));
                                did_attach = true;


@@ 595,7 597,7 @@ pub async fn handle_client(
                                    &mut entities,
                                    parent_id,
                                    player_id,
                                    module.clone().ok_or("module does not exist")?,
                                    &module.clone().ok_or("module does not exist")?,
                                    3,
                                ));
                                did_attach = true;


@@ 605,7 607,7 @@ pub async fn handle_client(
                                    &mut entities,
                                    parent_id,
                                    player_id,
                                    module.clone().ok_or("module does not exist")?,
                                    &module.clone().ok_or("module does not exist")?,
                                    1,
                                ));
                                did_attach = true;


@@ 629,7 631,8 @@ pub async fn handle_client(
                                .ok_or("attached module does not exist")?
                                .to_protocol(&entities, &data_handle.rigid_body_set);
                            let msg = MessageS2C::ModuleAdd(MessageS2CModuleAdd {
                                module: Some(prot_module.ok_or("attached module does not exist")?).into(),
                                module: Some(prot_module.ok_or("attached module does not exist")?)
                                    .into(),
                                special_fields: SpecialFields::default(),
                            })
                            .try_into()?;

M server/src/main.rs => server/src/main.rs +9 -2
@@ 148,7 148,8 @@ async fn _handle_request(
        Err(e) if e.is::<async_tungstenite::tungstenite::error::Error>() => {
            #[allow(clippy::expect_used)]
            let e = {
                e.downcast::<async_tungstenite::tungstenite::error::Error>().expect("unable to convert between types safely")
                e.downcast::<async_tungstenite::tungstenite::error::Error>()
                    .expect("unable to convert between types safely")
            };

            if matches!(*e, async_tungstenite::tungstenite::Error::ConnectionClosed) {


@@ 304,7 305,13 @@ async fn main() {
    let physics_data = DATA.clone();
    let entities_timer = ENTITIES.clone();
    let _timer_thread = async_std::task::spawn(async move {
        timer_main(mgr_timer, physics_data, entities_timer).await;
        match timer_main(mgr_timer, physics_data, entities_timer).await {
            Ok(_) => (),
            Err(e) => {
                error!("timer thread exited with error: {}", e);
                std::process::exit(1);
            }
        }
    });

    let try_socket = TcpListener::bind(&addr).await;

M server/src/manager.rs => server/src/manager.rs +7 -2
@@ 34,6 34,7 @@ pub struct Player {
}

impl Player {
    #[allow(clippy::missing_const_for_fn)] // This will eventually do something, but for now it doesn't
    pub fn as_api_data(&self) -> APISavedPlayerData {
        APISavedPlayerData {}
    }


@@ 61,9 62,12 @@ impl Player {
                    entities.entities.get(&attachment.child)?
                {
                    if *child_module == *module {
                        return Some((u8::try_from(slot).ok()?, entities.get_player_id(self.addr)?));
                        return Some((
                            u8::try_from(slot).ok()?,
                            entities.get_player_id(self.addr)?,
                        ));
                    }
                    let parent = child_module.find_parent(module.clone(), entities);
                    let parent = child_module.find_parent(module, entities);
                    if parent.is_some() {
                        return parent;
                    }


@@ 75,6 79,7 @@ impl Player {
}

#[derive(Default, Clone, Debug)]
#[allow(clippy::struct_excessive_bools)]
pub struct PlayerInput {
    pub up: bool,
    pub left: bool,

M server/src/module.rs => server/src/module.rs +57 -46
@@ 2,6 2,7 @@ use std::error::Error;
use std::f64::consts::PI;

use nalgebra::{point, vector, Isometry2, Unit, Vector2};
use protobuf::SpecialFields;
use rapier2d_f64::prelude::{
    ColliderBuilder, FixedJointBuilder, ImpulseJointHandle, MassProperties, Real, RigidBodyBuilder,
    RigidBodyHandle, RigidBodySet,


@@ 29,7 30,7 @@ pub struct ModuleTemplate {
    pub module_type: ModuleType,
}

#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AttachedModule {
    pub handle: RigidBodyHandle,
    pub module_type: ModuleType,


@@ 42,7 43,7 @@ impl AttachedModule {
        entities: &mut EntityHandler,
        parent: EntityId,
        player_id: EntityId,
        module: Module,
        module: &Module,
        attachment_slot: usize,
    ) -> Result<EntityId, Box<dyn Error + Send + Sync>> {
        let mut entity_map = entities.entities.clone();


@@ 70,7 71,8 @@ impl AttachedModule {

        let parent_body = data
            .rigid_body_set
            .get(parent_handle).ok_or("parent body does not exist")?;
            .get(parent_handle)
            .ok_or("parent body does not exist")?;
        let parent_pos = vector![parent_body.translation().x, parent_body.translation().y];
        let parent_angle = parent_body.rotation().angle();
        let parent_linvel = *parent_body.linvel();


@@ 84,13 86,22 @@ impl AttachedModule {
            _ => (point![0. / SCALE, 53. / SCALE], 0.),
        };

        if let Some(id) = entities.get_from_module(&module) {
        if let Some(id) = entities.get_from_module(module) {
            let relative_pos = vector![
                anchor.x.mul_add((parent_body.rotation().angle()).cos(), anchor.y * -(parent_body.rotation().angle()).sin()),
                anchor.x.mul_add((parent_body.rotation().angle()).sin(), anchor.y * (parent_body.rotation().angle()).cos())
                anchor.x.mul_add(
                    (parent_body.rotation().angle()).cos(),
                    anchor.y * -(parent_body.rotation().angle()).sin()
                ),
                anchor.x.mul_add(
                    (parent_body.rotation().angle()).sin(),
                    anchor.y * (parent_body.rotation().angle()).cos()
                )
            ];
            let module_pos = parent_pos + relative_pos;
            let module_body = data.rigid_body_set.get_mut(module.handle).ok_or("module body does not exist")?;
            let module_body = data
                .rigid_body_set
                .get_mut(module.handle)
                .ok_or("module body does not exist")?;
            module_body.set_translation(module_pos, true);
            module_body.set_rotation(Unit::from_angle(parent_angle + rotation), true);
            module_body.set_linvel(parent_linvel, true);


@@ 139,16 150,15 @@ impl AttachedModule {
        data: &mut PhysicsData,
        entities: &mut EntityHandler,
        player_id: EntityId,
        module: Self,
        module: &Self,
    ) -> Option<EntityId> {
        let mut entity_map = entities.entities.clone();

        // player not in parent search
        // also no parents included in parent search
        let player = entities.get_player_from_id(player_id)?;
        let (slot, parent_id) = player.find_parent(&module, entities)?;
        let parent_entity = entity_map
            .get_mut(&parent_id)?;
        let (slot, parent_id) = player.find_parent(module, entities)?;
        let parent_entity = entity_map.get_mut(&parent_id)?;

        match parent_entity {
            Entity::Player(ref mut player) => {


@@ 175,24 185,22 @@ impl AttachedModule {
            lifetime: 0.,
            flags: 0,
        };
        entity_map.remove(&entities.get_id_from_attached(&module)?);
        entity_map.remove(&entities.get_id_from_attached(module)?);
        let id = get_entity_id();
        entity_map.insert(id, Entity::Module(new_module));
        for element in tree {
            for child in element.clone().children {
                if let Some(child) = child {
                    data.impulse_joint_set.remove(child.connection, true);
                    let child_body = entities.get_attached_from_id(child.child)?;
                    let new_module = Module {
                        handle: child_body.handle,
                        module_type: child_body.module_type,
                        lifetime: 0.,
                        flags: 0,
                    };
                    entity_map.remove(&entities.get_id_from_attached(&child_body)?);
                    let attached_id = get_entity_id();
                    entity_map.insert(attached_id, Entity::Module(new_module));
                }
            for child in element.clone().children.into_iter().flatten() {
                data.impulse_joint_set.remove(child.connection, true);
                let child_body = entities.get_attached_from_id(child.child)?;
                let new_module = Module {
                    handle: child_body.handle,
                    module_type: child_body.module_type,
                    lifetime: 0.,
                    flags: 0,
                };
                entity_map.remove(&entities.get_id_from_attached(&child_body)?);
                let attached_id = get_entity_id();
                entity_map.insert(attached_id, Entity::Module(new_module));
            }
        }
        entities.entities = entity_map;


@@ 203,13 211,12 @@ impl AttachedModule {
        entities: &mut EntityHandler,
        parent: EntityId,
        player_id: EntityId,
        module: ModuleTemplate,
        module: &ModuleTemplate,
        attachment_slot: usize,
    ) -> Option<EntityId> {
        let mut entity_map = entities.entities.clone();

        let parent_entity = entity_map
            .get_mut(&parent)?;
        let parent_entity = entity_map.get_mut(&parent)?;
        let parent_handle = match parent_entity {
            Entity::Player(player) => player.handle,
            Entity::AttachedModule(module) => module.handle,


@@ 218,9 225,7 @@ impl AttachedModule {
            }
        };

        let parent_body = data
            .rigid_body_set
            .get(parent_handle)?;
        let parent_body = data.rigid_body_set.get(parent_handle)?;
        let parent_pos = vector![parent_body.translation().x, parent_body.translation().y];

        let (anchor, rotation) = match attachment_slot {


@@ 232,8 237,14 @@ impl AttachedModule {
        };

        let relative_pos = vector![
            anchor.x.mul_add((parent_body.rotation().angle()).cos(), anchor.y * -(parent_body.rotation().angle()).sin()),
            anchor.x.mul_add((parent_body.rotation().angle()).sin(), anchor.y * (parent_body.rotation().angle()).cos())
            anchor.x.mul_add(
                (parent_body.rotation().angle()).cos(),
                anchor.y * -(parent_body.rotation().angle()).sin()
            ),
            anchor.x.mul_add(
                (parent_body.rotation().angle()).sin(),
                anchor.y * (parent_body.rotation().angle()).cos()
            )
        ];
        let module_pos = parent_pos + relative_pos;



@@ 289,7 300,7 @@ impl AttachedModule {
        Some(attached_id)
    }
    // TODO: remove this function
    pub fn to_module(&self) -> Module {
    pub const fn to_module(&self) -> Module {
        Module {
            handle: self.handle,
            module_type: self.module_type,


@@ 297,6 308,7 @@ impl AttachedModule {
            flags: 0,
        }
    }

    // TODO: this one too
    pub fn to_module_id(&self, entities: &EntityHandler) -> Option<(EntityId, Module)> {
        Some((


@@ 322,8 334,8 @@ impl AttachedModule {
            if let Some(Some(child)) = children.get(i) {
                prot_children.push(starkingdoms_protocol::module::Attachment {
                    id: child.child,
                    slot: i as u32,
                    special_fields: Default::default(),
                    slot: u32::try_from(i).ok()?,
                    special_fields: SpecialFields::default(),
                });
            }
        }


@@ 334,7 346,7 @@ impl AttachedModule {
            y: body.translation().y * SCALE,
            id: entities.get_id_from_attached(self)?,
            children: prot_children,
            special_fields: Default::default(),
            special_fields: SpecialFields::default(),
        })
    }



@@ 350,20 362,19 @@ impl AttachedModule {
        modules
    }

    pub fn find_parent(
        &self,
        module: Self,
        entities: &EntityHandler,
    ) -> Option<(u8, EntityId)> {
    pub fn find_parent(&self, module: &Self, entities: &EntityHandler) -> Option<(u8, EntityId)> {
        for (slot, attachment) in self.children.iter().enumerate() {
            if let Some(attachment) = attachment {
                if let Entity::AttachedModule(child_module) =
                    entities.entities.get(&attachment.child)?
                {
                    if *child_module == module {
                        return Some((slot as u8, entities.get_id_from_attached(self)?));
                    if *child_module == *module {
                        return Some((
                            u8::try_from(slot).ok()?,
                            entities.get_id_from_attached(self)?,
                        ));
                    }
                    let parent = child_module.find_parent(module.clone(), entities);
                    let parent = child_module.find_parent(module, entities);
                    if parent.is_some() {
                        return parent;
                    }

M server/src/planet.rs => server/src/planet.rs +6 -7
@@ 1,4 1,5 @@
use nalgebra::{vector, Vector2};
use protobuf::SpecialFields;
use rapier2d_f64::prelude::{
    ColliderBuilder, ColliderSet, RigidBodyBuilder, RigidBodyHandle, RigidBodySet,
};


@@ 48,7 49,7 @@ impl Planets {
        self.planets.get_mut(planet_id)
    }

    pub async fn make_planet(
    pub fn make_planet(
        _planet_id: &str,
        planet_type: PlanetType,
        mass: f64,


@@ 79,7 80,7 @@ impl Planets {
        )
    }

    pub async fn create_planets(
    pub fn create_planets(
        rigid_body_set: &mut RigidBodySet,
        collider_set: &mut ColliderSet,
        entities: &mut Entities,


@@ 93,8 94,7 @@ impl Planets {
            (100.0, 100.0),
            rigid_body_set,
            collider_set,
        )
        .await;
        );
        entities.insert(earth_id, entity);
        planet_ids.push(earth_id);



@@ 117,8 117,7 @@ impl Planets {
            (moon_start_point[0], moon_start_point[1]),
            rigid_body_set,
            collider_set,
        )
        .await;
        );
        entities.insert(moon_id, moon);
        planet_ids.push(moon_id);
        planet_ids


@@ 134,7 133,7 @@ impl Planets {
                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: Default::default(),
                special_fields: SpecialFields::default(),
            });
        }


M server/src/timer.rs => server/src/timer.rs +68 -24
@@ 14,11 14,12 @@ use async_std::sync::RwLock;
use async_std::task::sleep;
use log::warn;
use nalgebra::{point, vector};
use protobuf::SpecialFields;
use rand::Rng;
use rapier2d_f64::prelude::{ColliderBuilder, MassProperties, PhysicsPipeline, RigidBodyBuilder};
use starkingdoms_protocol::{module::ModuleType, planet::PlanetType, player::Player};
use std::{f64::consts::PI, sync::Arc, time::Duration};
use std::error::Error;
use std::{f64::consts::PI, sync::Arc, time::Duration};

pub const LATERAL_FORCE: f64 = 0.0002;
pub const MODULE_SPAWN: f64 = 3.0;


@@ 34,7 35,6 @@ pub async fn timer_main(

    let mut time = 0.0;
    let mut module_timer = 0.0;
    let _planet_ids;

    {
        let mut data_handle = physics_data_orig.write().await;


@@ 42,17 42,18 @@ pub async fn timer_main(
        let mut rigid_body_set = data_handle.rigid_body_set.clone();
        let mut collider_set = data_handle.collider_set.clone();

        _planet_ids = Planets::create_planets(
        let _ = Planets::create_planets(
            &mut rigid_body_set,
            &mut collider_set,
            &mut entities.write().await.entities,
        )
        .await;
        );

        data_handle.rigid_body_set = rigid_body_set;
        data_handle.collider_set = collider_set;
    }

    #[allow(clippy::significant_drop_tightening)]
    // underdeveloped lint, TODO remove when its better
    loop {
        sleep(Duration::from_millis(5)).await;
        time += 5.0 / 1000.0; // 5ms, time is in seconds


@@ 68,11 69,15 @@ pub async fn timer_main(
            let planets = entities.write().await;

            // update earth (nothing changes, yet)
            let earth = planets.get_planet(PlanetType::Earth).ok_or("earth does not exist")?;
            let earth = planets
                .get_planet(PlanetType::Earth)
                .ok_or("earth does not exist")?;
            let new_earth_position = vector![earth.position.0, earth.position.1];

            // update moon
            let moon: &mut Planet = &mut planets.get_planet(PlanetType::Moon).ok_or("moon does not exist")?;
            let moon: &mut Planet = &mut planets
                .get_planet(PlanetType::Moon)
                .ok_or("moon does not exist")?;
            let new_moon_position = calculate_world_position_of_orbit(
                calculate_point_on_orbit(MOON_PERIAPSIS, MOON_APOAPSIS, time / MOON_ORBIT_TIME),
                new_earth_position,


@@ 139,7 144,10 @@ pub async fn timer_main(
            let mut entities = entities.write().await;
            for module in &mut entities.get_modules() {
                let module_handle = module.handle;
                let module_body = physics_data.rigid_body_set.get_mut(module_handle).ok_or("module does not exist")?;
                let module_body = physics_data
                    .rigid_body_set
                    .get_mut(module_handle)
                    .ok_or("module does not exist")?;
                module_body.reset_forces(true);
                module_body.reset_torques(true);
                let grav_force = entities.gravity(


@@ 147,8 155,14 @@ pub async fn timer_main(
                    module_body.mass(),
                );
                module_body.apply_impulse(vector![grav_force.0, grav_force.1], true);
                let id = entities.get_from_module(module).ok_or("module entity does not exist")?;
                if let Entity::Module(p_module) = entities.entities.get_mut(&id).ok_or("module does not exist")? {
                let id = entities
                    .get_from_module(module)
                    .ok_or("module entity does not exist")?;
                if let Entity::Module(p_module) = entities
                    .entities
                    .get_mut(&id)
                    .ok_or("module does not exist")?
                {
                    p_module.lifetime += 5. / 1000.;
                }
                if module.lifetime > 80. {


@@ 175,7 189,10 @@ pub async fn timer_main(
            }
            for module in &mut entities.get_all_attached() {
                let module_handle = module.handle;
                let module_body = physics_data.rigid_body_set.get_mut(module_handle).ok_or("module does not exist")?;
                let module_body = physics_data
                    .rigid_body_set
                    .get_mut(module_handle)
                    .ok_or("module does not exist")?;
                module_body.reset_forces(true);
                module_body.reset_torques(true);
                let grav_force = entities.gravity(


@@ 189,7 206,10 @@ pub async fn timer_main(
        {
            for (player_id, player) in &entities.read().await.get_players() {
                let player_handle = player.handle;
                let player_body = physics_data.rigid_body_set.get_mut(player_handle).ok_or("player body does not exist")?;
                let player_body = physics_data
                    .rigid_body_set
                    .get_mut(player_handle)
                    .ok_or("player body does not exist")?;
                player_body.reset_forces(true);
                player_body.reset_torques(true);
                let planets = entities.read().await;


@@ 271,7 291,10 @@ pub async fn timer_main(
                let username;
                {
                    let usernames = mgr.usernames.read().await;
                    username = usernames.get(player_id).ok_or("username does not exist")?.clone();
                    username = usernames
                        .get(player_id)
                        .ok_or("username does not exist")?
                        .clone();
                }

                protocol_players.push(Player {


@@ 279,7 302,7 @@ pub async fn timer_main(
                    x: (translation.x * SCALE),
                    y: (translation.y * SCALE),
                    username,
                    special_fields: Default::default(),
                    special_fields: SpecialFields::default(),
                });
            }
        }


@@ 315,15 338,20 @@ pub async fn timer_main(
                            .iter()
                            .filter(|m| match this_player {
                                Some(id) => {
                                    if m.player_id != id {
                                        true
                                    } else {
                                        #[allow(clippy::expect_used)] {
                                    if m.player_id == id {
                                        #[allow(clippy::expect_used)]
                                        {
                                            attached_modules.push(
                                                m.to_protocol(&entities, &physics_data.rigid_body_set).expect("module does not exist"),
                                                m.to_protocol(
                                                    &entities,
                                                    &physics_data.rigid_body_set,
                                                )
                                                .expect("module does not exist"),
                                            );
                                        }
                                        false
                                    } else {
                                        true
                                    }
                                }
                                None => true,


@@ 331,10 359,20 @@ pub async fn timer_main(
                            .map(|m| {
                                let id;
                                let module;
                                #[allow(clippy::expect_used)] { (id, module) = m.to_module_id(&entities).expect("unable to get module id"); }
                                #[allow(clippy::expect_used)]
                                {
                                    (id, module) =
                                        m.to_module_id(&entities).expect("unable to get module id");
                                }
                                //info!("{:?}", module);
                                let body;
                                #[allow(clippy::expect_used)] { body = physics_data.rigid_body_set.get(module.handle).expect("module body does not exist"); }
                                #[allow(clippy::expect_used)]
                                {
                                    body = physics_data
                                        .rigid_body_set
                                        .get(module.handle)
                                        .expect("module body does not exist");
                                }

                                starkingdoms_protocol::module::Module {
                                    module_type: module.module_type.into(),


@@ 343,7 381,7 @@ pub async fn timer_main(
                                    y: body.translation().y * SCALE,
                                    id,
                                    flags: module.flags,
                                    special_fields: Default::default(),
                                    special_fields: SpecialFields::default(),
                                }
                            })
                            .collect();


@@ 352,7 390,13 @@ pub async fn timer_main(
                        .map(|(id, module)| {
                            let body;

                            #[allow(clippy::expect_used)] { body = physics_data.rigid_body_set.get(module.handle).expect("module body does not exist"); }
                            #[allow(clippy::expect_used)]
                            {
                                body = physics_data
                                    .rigid_body_set
                                    .get(module.handle)
                                    .expect("module body does not exist");
                            }

                            starkingdoms_protocol::module::Module {
                                module_type: module.module_type.into(),


@@ 361,7 405,7 @@ pub async fn timer_main(
                                y: body.translation().y * SCALE,
                                id: *id,
                                flags: module.flags,
                                special_fields: Default::default(),
                                special_fields: SpecialFields::default(),
                            }
                        })
                        .collect();