~starkingdoms/starkingdoms

b13d8b9b2bf3ce194c60aaede8450d9f03744f30 — ghostlyzsh 1 year, 11 months ago aae675f
loading but rust is angry
3 files changed, 281 insertions(+), 107 deletions(-)

M server/src/component.rs
M server/src/main.rs
M starkingdoms-common/src/lib.rs
M server/src/component.rs => server/src/component.rs +13 -1
@@ 35,7 35,7 @@ pub enum PartType {
    LandingThruster,
    LandingThrusterSuspension,
}
impl From<PartType> for starkingdoms_common::PartType {
impl From<PartType> for c_PartType {
    fn from(value: PartType) -> Self {
        match value {
            PartType::Placeholder => c_PartType::Placeholder,


@@ 47,6 47,18 @@ impl From<PartType> for starkingdoms_common::PartType {
        }
    }
}
impl From<c_PartType> for PartType {
    fn from(value: c_PartType) -> Self {
        match value {
            c_PartType::Placeholder => PartType::Placeholder,
            c_PartType::Hearty => PartType::Hearty,
            c_PartType::Cargo => PartType::Cargo,
            c_PartType::Hub => PartType::Hub,
            c_PartType::LandingThruster => PartType::LandingThruster,
            c_PartType::LandingThrusterSuspension => PartType::LandingThrusterSuspension,
        }
    }
}

#[derive(Component, Clone, Debug)]
pub struct Attach {

M server/src/main.rs => server/src/main.rs +255 -99
@@ 79,7 79,7 @@ fn main() {
        .add_systems(Startup, setup_integration_parameters)
        .add_systems(Startup, spawn_planets)
        .add_systems(FixedUpdate, module_spawn)
        .add_systems(Update, on_message)
        .add_systems(Update, (on_message, on_login).chain())
        .add_systems(Update, on_close)
        .add_systems(FixedUpdate, on_position_change)
        .add_systems(


@@ 212,41 212,12 @@ fn module_spawn(
    }
}

fn on_message(
    mut commands: Commands,
    planet_query: Query<(Entity, &PlanetType, &Transform)>,
    mut part_query: Query<
        (
            Entity,
            &PartType,
            &mut Transform,
            &mut Velocity,
            Option<&LooseAttach>,
            &mut PartFlags,
        ),
        (Without<PlanetType>, Without<Player>, Without<Attach>),
    >,
    mut attached_query: Query<
        (
            Entity,
            &PartType,
            &mut Transform,
            &mut Attach,
            &Velocity,
            Option<&CanAttach>,
            Option<&LooseAttach>,
            &mut PartFlags,
        ),
        (Without<PlanetType>, Without<Player>),
    >,
    mut player_query: Query<
        (Entity, &mut Player, &Transform, &Velocity, &mut Attach),
        Without<PlanetType>,
    >,
fn on_login(
    world: &mut World,
    mut packet_recv: Local<ManualEventReader<ServerEvent>>,
    mut packet_event_send: ResMut<Events<ServerEvent>>,
    app_keys: Res<AppKeys>,
    mut packet_event_send: Local<Events<ServerEvent>>,
) {
    let app_keys = world.resource::<AppKeys>().clone();
    let mut event_queue = Vec::new();
    for ev in packet_recv.read(&packet_event_send) {
        if let ServerEvent::Recv(addr, MessageType::Text, data) = ev {


@@ 255,24 226,6 @@ fn on_message(

            match packet {
                Packet::ClientLogin { username, save } => {
                    if let Some(save) = save {
                        // attempt to decode the savefile
                        if let Ok(savefile) = unpack_savefile(&app_keys.app_key, save) {
                            // HEY! GHOSTLY! THIS SAVE FILE IS VALID! PLEASE LOAD IT!
                            // THANKS!
                        } else {
                            let packet = Packet::Message {
                                message_type: packet::MessageType::Error,
                                actor: "SERVER".to_string(),
                                content: "Savefile signature corrupted or inner data invalid. Save was not loaded. Contact StarKingdoms staff for assistance.".to_string(),
                            };
                            let buf = serde_json::to_vec(&packet).unwrap();
                            event_queue.push(ServerEvent::Send(*addr, MessageType::Text, buf));
                        }
                    } else {
                        // nothing to do
                    }

                    let angle: f32 = {
                        let mut rng = rand::thread_rng();
                        rng.gen::<f32>() * std::f32::consts::PI * 2.


@@ 283,7 236,7 @@ fn on_message(
                        0.0,
                    );
                    transform.rotate_z(angle);
                    let entity_id = commands
                    let mut entity_id = world
                        .spawn(PlayerBundle {
                            part: PartBundle {
                                part_type: PartType::Hearty,


@@ 302,8 255,8 @@ fn on_message(
                                parent: None,
                                children: [None, None, None, None],
                            },
                        })
                        .insert(Collider::cuboid(
                        });
                    entity_id.insert(Collider::cuboid(
                            PART_HALF_SIZE / SCALE,
                            PART_HALF_SIZE / SCALE,
                        ))


@@ 319,13 272,14 @@ fn on_message(
                        .insert(ExternalForce::default())
                        .insert(ReadMassProperties::default())
                        .insert(Velocity::default())
                        .insert(RigidBody::Dynamic)
                        .id();
                    let id = entity_id.index();
                        .insert(RigidBody::Dynamic);
                    let id = entity_id.id().index();


                    let mut planet_query = world.query::<(Entity, &PlanetType, &Transform)>();
                    // tell this player the planets
                    let mut planets = Vec::new();
                    for (entity, planet_type, transform) in planet_query.iter() {
                    for (entity, planet_type, transform) in planet_query.iter(&world) {
                        let translation = transform.translation;
                        planets.push((
                            entity.index(),


@@ 347,8 301,9 @@ fn on_message(
                    event_queue.push(ServerEvent::Send(*addr, MessageType::Text, buf));

                    // tell the player already existing users
                    let mut player_query = world.query_filtered::<(Entity, &mut Player, &Transform, &Velocity, &mut Attach), Without<PlanetType>>();
                    let mut players = Vec::new();
                    for (entity, player, _, _, _) in &player_query {
                    for (entity, player, _, _, _) in player_query.iter(&world) {
                        players.push((entity.index(), player.username.clone()));
                    }
                    let packet = Packet::PlayerList { players };


@@ 371,8 326,11 @@ fn on_message(
                    event_queue.push(ServerEvent::Broadcast(MessageType::Text, buf));

                    // tell the player where parts are
                    let mut part_query = world.query_filtered::<(Entity, &PartType, &mut Transform, &mut Velocity,
                                                                 Option<&LooseAttach>, &mut PartFlags),
                                                             (Without<PlanetType>, Without<Player>, Without<Attach>)>();
                    let mut parts = Vec::new();
                    for (entity, part_type, transform, _, _, flags) in &part_query {
                    for (entity, part_type, transform, _, _, flags) in part_query.iter(&world) {
                        parts.push((
                            entity.index(),
                            Part {


@@ 384,7 342,10 @@ fn on_message(
                            },
                        ));
                    }
                    for (entity, part_type, transform, _, _, _, _, flags) in &attached_query {
                    let mut attached_query = world.query_filtered::<(Entity, &PartType, &mut Transform,
                                                                 &mut Attach, &Velocity, Option<&CanAttach>, Option<&LooseAttach>, &mut PartFlags),
                                                                 (Without<PlanetType>, Without<Player>)>();
                    for (entity, part_type, transform, _, _, _, _, flags) in attached_query.iter(&world) {
                        parts.push((
                            entity.index(),
                            Part {


@@ 419,47 380,241 @@ fn on_message(
                    };
                    let buf = serde_json::to_vec(&packet).unwrap();
                    event_queue.push(ServerEvent::Send(*addr, MessageType::Text, buf));
                }
                Packet::SendMessage { target, content } => {
                    // find our player
                    let mut player = None;
                    for (_, q_player, _, _, _) in &player_query {
                        if q_player.addr == *addr {
                            player = Some(q_player);
                        }
                    }
                    let player = player.unwrap();
                    if let Some(target_username) = target {
                        let mut target_player = None;
                        for (_, q_player, _, _, _) in &player_query {
                            if q_player.username == target_username {
                                target_player = Some(q_player);
                            }
                    if let Some(save) = save {
                        // attempt to decode the savefile
                        if let Ok(savefile) = unpack_savefile(&app_keys.app_key, save) {
                            // HEY! GHOSTLY! THIS SAVE FILE IS VALID! PLEASE LOAD IT!
                            // THANKS!
                            let mut attach = entity_id.get_mut::<Attach>().unwrap();
                            load_savefile(world, transform, entity_id.id(), entity_id.id(), &mut attach, savefile.children, &mut attached_query, &mut part_query);
                        } else {
                            let packet = Packet::Message {
                                message_type: packet::MessageType::Error,
                                actor: "SERVER".to_string(),
                                content: "Savefile signature corrupted or inner data invalid. Save was not loaded. Contact StarKingdoms staff for assistance.".to_string(),
                            };
                            let buf = serde_json::to_vec(&packet).unwrap();
                            event_queue.push(ServerEvent::Send(*addr, MessageType::Text, buf));
                        }
                        let target_player = target_player.unwrap();
                        let packet = Packet::Message {
                            message_type: packet::MessageType::Direct,
                            actor: player.username.clone(),
                            content,
                        };
                        let buf = serde_json::to_vec(&packet).unwrap();
                        event_queue.push(ServerEvent::Send(
                            target_player.addr,
                            MessageType::Text,
                            buf.clone(),
                        ));
                        event_queue.push(ServerEvent::Send(*addr, MessageType::Text, buf));
                    } else {
                        // send to general chat
                        let packet = Packet::Message {
                            message_type: packet::MessageType::Chat,
                            actor: player.username.clone(),
                            content,
                        };
                        let buf = serde_json::to_vec(&packet).unwrap();
                        event_queue.push(ServerEvent::Broadcast(MessageType::Text, buf));
                        // nothing to do
                    }
                }
                _ => {}
            }
        }
    }
    for event in event_queue {
        packet_event_send.send(event);
    }
}

fn load_savefile(
    world: &mut World,
    transform: Transform,
    player_id: Entity,
    parent: Entity,
    parent_attach: &mut Attach,
    children: Vec<Option<SaveModule>>,
    attached_query: &mut QueryState<
        (
            Entity,
            &PartType,
            &mut Transform,
            &mut Attach,
            &Velocity,
            Option<&CanAttach>,
            Option<&LooseAttach>,
            &mut PartFlags,
        ),
        (Without<PlanetType>, Without<Player>),
    >,
    part_query: &mut QueryState<
        (
            Entity,
            &PartType,
            &mut Transform,
            &mut Velocity,
            Option<&LooseAttach>,
            &mut PartFlags,
        ),
        (Without<PlanetType>, Without<Player>, Without<Attach>),
    >,
) -> bool {
    let mut ret = false;
    for (i, child) in children.iter().enumerate() {
        if let Some(child) = child {
            //let attachable = can_attach != None;
            
            let p_pos = transform.translation;
            let angle = transform.rotation.to_euler(EulerRot::ZYX).0;
            let mut offset = Vec2::ZERO;
            let mut angle_offset = 0.;
            if i == 2 {
                offset = Vec2::new(53., -53.);
                angle_offset = 0.;
            } else if i == 0 {
                offset = Vec2::new(-53., 53.);
                angle_offset = PI;
            } else if i == 1 {
                offset = Vec2::new(53., 53.);
                angle_offset = PI / 2.;
            } else if i == 3 {
                offset = Vec2::new(-53., -53.);
                angle_offset = -PI / 2.;
            }
            let mut module = world.spawn(PartBundle {
                transform: TransformBundle::from(Transform::from_xyz(
                               p_pos.x + offset.x / SCALE * angle.cos(),
                               p_pos.y + offset.y / SCALE * angle.sin(),
                               0.,
                           ).with_rotation(Quat::from_euler(EulerRot::ZYX, angle + angle_offset, 0., 0.))),
                part_type: child.part_type.into(),
                flags: PartFlags { attached: true },
            });
            module.insert(RigidBody::Dynamic)
            .with_children(|children| {
                children
                    .spawn(Collider::cuboid(18.75 / SCALE, 23.4375 / SCALE))
                    .insert(TransformBundle::from(Transform::from_xyz(
                        0.,
                        1.5625 / SCALE,
                        0.,
                    )));
            })
            .insert(AdditionalMassProperties::MassProperties(MassProperties {
                local_center_of_mass: vec2(0.0, 0.0),
                mass: 0.0001,
                principal_inertia: 0.005,
            }))
            .insert(ExternalForce::default())
            .insert(ExternalImpulse::default())
            .insert(Velocity::default())
            .insert(ReadMassProperties::default());
            let joint = FixedJointBuilder::new()
                .local_anchor1(vec2(-53. / SCALE, 0. / SCALE))
                .local_basis2(-PI / 2.);
            let mut children = [None, None, None, None];
            if PartType::from(child.part_type) == PartType::LandingThruster {
                module.insert(Attach {
                        associated_player: Some(player_id),
                        parent: Some(module.id()),
                        children: [None, None, None, None],
                    });
                let joint = PrismaticJointBuilder::new(Vec2::new(0., 1.))
                    .local_anchor1(Vec2::new(0., 0.))
                    .local_anchor2(Vec2::new(0., 0.))
                    .motor_position(0., 150., 10.)
                    .limits([0., 50. / SCALE])
                    .build();
                let mut suspension = world.spawn(PartBundle {
                    transform: TransformBundle::from(Transform::from_xyz(
                                   p_pos.x + offset.x / SCALE * angle.cos(),
                                   p_pos.y + offset.y / SCALE * angle.sin(),
                                   0.,
                               ).with_rotation(Quat::from_euler(EulerRot::ZYX, angle + angle_offset, 0., 0.))),
                    part_type: PartType::LandingThrusterSuspension,
                    flags: PartFlags { attached: false },
                });
                suspension
                    .insert(RigidBody::Dynamic)
                    .with_children(|children| {
                        children
                            .spawn(Collider::cuboid(PART_HALF_SIZE / SCALE, 1. / SCALE))
                            .insert(TransformBundle::from(Transform::from_xyz(
                                0.,
                                -24. / SCALE,
                                0.,
                            )));
                    })
                    .insert(ImpulseJoint::new(module.id(), joint))
                    .insert(ExternalForce::default())
                    .insert(ExternalImpulse::default())
                    .insert(Velocity::default())
                    .insert(ReadMassProperties::default())
                    .insert(AdditionalMassProperties::MassProperties(MassProperties {
                        local_center_of_mass: vec2(0.0, 0.0),
                        mass: 0.00000000000001,
                        principal_inertia: 0.0000000000001,
                    }))
                    .insert(Attach {
                        associated_player: Some(player_id),
                        parent: Some(module.id()),
                        children: [None, None, None, None],
                    });
                children[2] = Some(suspension.id());
            }
            module.insert(ImpulseJoint::new(parent, joint));
            module.insert(Attach {
                associated_player: Some(player_id),
                parent: Some(parent),
                children,
            });
            parent_attach.children[i] = Some(module.id());
            //module.5.attached = true;

            ret = ret
                | if PartType::from(child.part_type) != PartType::LandingThruster {
                    load_savefile(
                        world,
                        transform,
                        player_id,
                        module.id(),
                        &mut module.get_mut::<Attach>().unwrap(),
                        child.children.clone(),
                        attached_query,
                        part_query,
                    )
                } else {
                    false
                };
        }
    }
    return ret;
}

fn on_message(
    mut commands: Commands,
    planet_query: Query<(Entity, &PlanetType, &Transform)>,
    mut part_query: Query<
        (
            Entity,
            &PartType,
            &mut Transform,
            &mut Velocity,
            Option<&LooseAttach>,
            &mut PartFlags,
        ),
        (Without<PlanetType>, Without<Player>, Without<Attach>),
    >,
    mut attached_query: Query<
        (
            Entity,
            &PartType,
            &mut Transform,
            &mut Attach,
            &Velocity,
            Option<&CanAttach>,
            Option<&LooseAttach>,
            &mut PartFlags,
        ),
        (Without<PlanetType>, Without<Player>),
    >,
    mut player_query: Query<
        (Entity, &mut Player, &Transform, &Velocity, &mut Attach),
        Without<PlanetType>,
    >,
    mut packet_recv: Local<ManualEventReader<ServerEvent>>,
    mut packet_event_send: ResMut<Events<ServerEvent>>,
    app_keys: Res<AppKeys>,
) {
    let mut event_queue = Vec::new();
    for ev in packet_recv.read(&packet_event_send) {
        if let ServerEvent::Recv(addr, MessageType::Text, data) = ev {
            let data = String::from_utf8_lossy(&data);
            let packet: Packet = err_or_cont!(serde_json::from_str(&data));

            match packet {
                Packet::PlayerInput {
                    up,
                    down,


@@ 911,6 1066,7 @@ fn on_message(
    }
}


fn construct_save_data(
    attach: Attach,
    attached_query: &Query<

M starkingdoms-common/src/lib.rs => starkingdoms-common/src/lib.rs +13 -7
@@ 20,7 20,7 @@ use serde::{Deserialize, Serialize};
use sha2::Sha256;
use std::error::Error;

#[derive(Serialize, Deserialize, Debug)]
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct SaveData {
    // ----------------------------------------------------------------------
    // HEY YOU


@@ 32,7 32,7 @@ pub struct SaveData {
    pub children: Vec<Option<SaveModule>>,
}

#[derive(Serialize, Deserialize, Debug)]
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct SaveModule {
    pub part_type: PartType,
    pub children: Vec<Option<SaveModule>>,


@@ 73,15 73,21 @@ pub fn pack_savefile(key: &str, save_data: SaveData) -> String {
}
pub fn unpack_savefile(key: &str, file: String) -> Result<SaveData, Box<dyn Error>> {
    // << reverse! <<
    let savefile_bytes = base64::engine::general_purpose::STANDARD.decode(file).map_err(|e| format!("error decoding b64: {e}"))?;
    let savefile_bytes = base64::engine::general_purpose::STANDARD
        .decode(file)
        .map_err(|e| format!("error decoding b64: {e}"))?;

    let save_file: Savefile = rmp_serde::from_slice(&savefile_bytes).map_err(|e| format!("error decoding savefile wrapper: {e}"))?;
    let save_file: Savefile = rmp_serde::from_slice(&savefile_bytes)
        .map_err(|e| format!("error decoding savefile wrapper: {e}"))?;

    let mut mac: Hmac<Sha256> = Hmac::new_from_slice(key.as_bytes()).map_err(|e| format!("error loading hmac-sha256: {e}"))?;
    let mut mac: Hmac<Sha256> = Hmac::new_from_slice(key.as_bytes())
        .map_err(|e| format!("error loading hmac-sha256: {e}"))?;
    mac.update(&save_file.data_msgpack);
    mac.verify_slice(&save_file.mac).map_err(|e| format!("error verifying signature: {e}"))?;
    mac.verify_slice(&save_file.mac)
        .map_err(|e| format!("error verifying signature: {e}"))?;

    let save_data = rmp_serde::from_slice(&save_file.data_msgpack).map_err(|e| format!("error decoding inner signature: {e}"))?;
    let save_data = rmp_serde::from_slice(&save_file.data_msgpack)
        .map_err(|e| format!("error decoding inner signature: {e}"))?;

    Ok(save_data)
}