~starkingdoms/starkingdoms

1991fb85e494fb35c0c5c9b6838f9e87c31b8908 — core 30 days ago 94b1b42
mystery work?
M crates/unified/assets/config/world.wc.toml => crates/unified/assets/config/world.wc.toml +1 -1
@@ 1,7 1,7 @@
[world]
gravity = 0.005
spawn_parts_at = "Earth"
spawn_parts_interval_secs = 10
spawn_parts_interval_secs = 1

[part]
default_height = 50

M crates/unified/src/attachment.rs => crates/unified/src/attachment.rs +1 -1
@@ 27,7 27,7 @@ pub struct Peer(#[entities] pub Entity);
#[derive(Component, Serialize, Deserialize, MapEntities)]
#[relationship(relationship_target = Joints)]
pub struct JointOf(#[entities] pub Entity);
#[derive(Component, Serialize, Deserialize, MapEntities)]
#[derive(Component, Serialize, Deserialize, MapEntities, Debug)]
#[relationship_target(relationship = JointOf)]
pub struct Joints(#[entities] Vec<Entity>);
impl Deref for Joints {

M crates/unified/src/client/parts.rs => crates/unified/src/client/parts.rs +35 -7
@@ 17,6 17,7 @@ pub fn parts_plugin(app: &mut App) {
            handle_incoming_parts,
            handle_updated_parts,
            update_drag_ghosts,
            update_part_sprites
        ),
    );
    app.add_observer(on_part_release);


@@ 24,12 25,17 @@ pub fn parts_plugin(app: &mut App) {

fn handle_incoming_parts(
    mut commands: Commands,
    new_parts: Query<(Entity, &Part), Added<Part>>,
    new_parts: Query<(Entity, &Part, Option<&PartInShip>), Added<Part>>,
    asset_server: Res<AssetServer>,
) {
    for (new_entity, new_part) in new_parts.iter() {
        let mut sprite =
            Sprite::from_image(asset_server.load(&new_part.strong_config.part.sprite_disconnected));
    for (new_entity, new_part, is_connected) in new_parts.iter() {
        let mut sprite = Sprite::from_image(
            asset_server.load(if is_connected.is_some() {
                &new_part.strong_config.part.sprite_connected
            } else {
                &new_part.strong_config.part.sprite_disconnected
            }),
        );
        sprite.custom_size = Some(Vec2::new(
            new_part.strong_config.physics.width,
            new_part.strong_config.physics.height,


@@ 49,12 55,16 @@ fn handle_incoming_parts(
}
fn handle_updated_parts(
    mut commands: Commands,
    updated_parts: Query<(Entity, &Part), Changed<Part>>,
    updated_parts: Query<(Entity, &Part, Option<&PartInShip>), Changed<Part>>,
    asset_server: Res<AssetServer>,
) {
    for (updated_entity, updated_part) in updated_parts.iter() {
    for (updated_entity, updated_part, is_connected) in updated_parts.iter() {
        let mut sprite = Sprite::from_image(
            asset_server.load(&updated_part.strong_config.part.sprite_disconnected),
            asset_server.load(if is_connected.is_some() {
                &updated_part.strong_config.part.sprite_connected
            } else {
                &updated_part.strong_config.part.sprite_disconnected
            }),
        );
        sprite.custom_size = Some(Vec2::new(
            updated_part.strong_config.physics.width,


@@ 74,6 84,24 @@ fn handle_updated_parts(
    }
}

fn update_part_sprites(added: Query<Entity, Added<PartInShip>>, mut removed: RemovedComponents<PartInShip>, parts: Query<(&Part, Option<&PartInShip>)>, asset_server: Res<AssetServer>, mut commands: Commands) {
    for e in added.into_iter().chain(removed.read()) {
        let Ok((part, connected_to)) = parts.get(e) else { continue };

        let sprite = if connected_to.is_some() { &part.strong_config.part.sprite_connected } else { &part.strong_config.part.sprite_disconnected };

        let mut sprite = Sprite::from_image(
            asset_server.load(sprite),
        );
        sprite.custom_size = Some(Vec2::new(
            part.strong_config.physics.width,
            part.strong_config.physics.height,
        ));

        commands.entity(e).insert(sprite);
    }
}

#[derive(Resource)]
struct DragResource(Option<Entity>);
#[derive(Resource)]

M crates/unified/src/server/player.rs => crates/unified/src/server/player.rs +39 -20
@@ 20,12 20,44 @@ pub fn player_management_plugin(app: &mut App) {
#[derive(Component)]
struct JointNeedsCreation(ImpulseJoint);

fn disconnect_part(
    entity: Entity,
    recursed_entity: Entity,
    joints: &Joints,
    q_joints: Query<&Joints>,
    q_peer: Query<(&Peer, &JointOf)>,

    mut commands: Commands,
) {
    trace!(?entity, ?joints, "recursive disconnect");
    // recursive disconnect part
    for joint in &**joints {
        let Ok((other_joint_handle, _)) = q_peer.get(*joint) else { continue };
        let other_joint = other_joint_handle.0;

        commands.entity(*joint).remove::<Peer>();

        let Ok((_, other_joint_of)) = q_peer.get(other_joint) else { continue };

        commands.entity(other_joint).remove::<Peer>();

        let Ok(joints) = q_joints.get(other_joint_of.0) else { continue };
        /*if other_joint != recursed_entity {
            disconnect_part(other_joint, entity, joints, q_joints, q_peer, commands.reborrow());
        } TODO this loops forever? */
    }
    commands.entity(entity).remove::<ImpulseJoint>();
    commands.entity(entity).remove::<PartInShip>();
}

fn dragging(
    mut events: EventReader<FromClient<DragRequestEvent>>,
    mut parts: Query<(&mut Transform, Option<&PartInShip>, Entity, &mut Velocity, &Joints), (With<Part>, Without<Joint>)>,
    snaps: Query<(&SnapOf, &SnapOfJoint)>,
    joints: Query<(&Joint, &JointOf, &Transform, Option<&Peer>, Entity)>,
    peer: Query<&Peer>,
    peer: Query<(&Peer, &JointOf)>,
    q_joints: Query<&Joints>,
    q_joint: Query<&ImpulseJoint>,
    clients: Query<&ConnectedNetworkEntity>,
    mut commands: Commands
) {


@@ 88,15 120,8 @@ fn dragging(

            // great, we have a valid peering request

            let mut did_disconnect = false;
            // disconnect it, if it is connected
            for joint in &**source_part.4 {
                let Ok(joint_peer) = peer.get(*joint) else { continue };
                did_disconnect = true;
                commands.entity(*joint).remove::<Peer>();
                commands.entity(joint_peer.0).remove::<Peer>();
            }
            commands.entity(source_part.2).remove::<ImpulseJoint>();
            let did_disconnect = q_joint.get(source_part.2).is_ok();
            disconnect_part(source_part.2, Entity::PLACEHOLDER, source_part.4, q_joints, peer, commands.reborrow());

            // create the peering component...
            commands.entity(source_joint.4)


@@ 133,13 158,13 @@ fn dragging(
            } else {
                // we disconnected this part this tick, and are performing a "reattachment"
                // (dragging an already attached part from peering point A to peering point B)
                

                // If we're reattaching to a different part, rapier will ignore our new attachment
                // as it will be seen as a mutation (removing and adding a component in the
                // same tick is considered equivalent to mutation by Bevy). 
                // same tick is considered equivalent to mutation by Bevy).
                // As Rapier does not allow you to mutate the source/destination of a joint,
                // the change will be outright ignored.
                

                // Since there is no (easy) way to get the real joint information back out of Rapier,
                // or to force it to accept what it sees as invalid mutation,
                // we need to delay the creation of the new joint by 1 tick so it's noticed by Rapier


@@ 157,13 182,7 @@ fn dragging(
            warn!("blindly accepting non-attachment request, someone should change this eventually");
            warn!("dragging already attached entities may cause inconsistent behavior!!");
            let source_part = parts.get(event.drag_target).unwrap();
            // disconnect it, if it is connected
            for joint in &**source_part.4 {
                let Ok(joint_peer) = peer.get(*joint) else { continue };
                commands.entity(*joint).remove::<Peer>();
                commands.entity(joint_peer.0).remove::<Peer>();
            }
            commands.entity(source_part.2).remove::<ImpulseJoint>();
            disconnect_part(source_part.2, Entity::PLACEHOLDER, source_part.4, q_joints, peer, commands.reborrow());
            teleport_to_translation = event.drag_to;
            teleport_to_rotation = event.set_rotation;
        }