~starkingdoms/starkingdoms

11ed44a250017a0508927b34f18a597d1db1ed7d — ghostly_zsh 9 days ago 5ccd4fb
feat: serverbound messages implemented but untested
M crates/unified/src/shared/ecs.rs => crates/unified/src/shared/ecs.rs +4 -4
@@ 44,13 44,13 @@ pub struct Player {
    pub client: Entity,
}

#[derive(Message, Debug, Clone)]
#[derive(Message, Debug, Clone, Serialize, Deserialize, TypePath)]
pub struct DragRequestEvent {
    pub drag_target: Entity,
    pub action: DragAction,
}

#[derive(Debug, Clone)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum DragAction {
    Attach { snap_target: Entity, peer_snap: Entity },
    Free   { position: Vec2, rotation: Quat },


@@ 66,7 66,7 @@ pub struct PlayerStorage {

#[derive(Component, Serialize, Deserialize, Debug)]
pub struct CanCraft;
#[derive(Message, Debug, Clone)]
#[derive(Message, Debug, Clone, Serialize, Deserialize, TypePath)]
pub struct CraftPartRequest {
    pub crafting_part: Entity,
    pub crafted_part: String,


@@ 92,7 92,7 @@ pub struct Drill {
    pub resource_multiplier: f32,
    pub on_planet: Option<String>,
}
#[derive(Message, Debug, Clone)]
#[derive(Message, Debug, Clone, Serialize, Deserialize, TypePath)]
pub struct ToggleDrillEvent {
    pub drill_entity: Entity,
}

M crates/unified/src/shared/net.rs => crates/unified/src/shared/net.rs +91 -17
@@ 12,11 12,12 @@ use bevy::ecs::system::SystemState;
use bevy::prelude::*;
use postcard::{from_bytes, to_allocvec, to_slice, to_vec};
use crate::prelude::{App, Message};
use crate::shared::thrust::ThrustSolution;
//use bevy_replicon::prelude::*;
use serde::{Deserialize, Serialize};
use crate::shared::attachment::{Joint, JointOf, PartInShip, Peer, Ship, SnapOf, SnapOfJoint};
use crate::shared::config::planet::{Planet, PlanetSpring, PlanetSpringJoint};
use crate::shared::ecs::{CanCraft, Drill, Part, Player, PlayerStorage, SingleStorage, Temperature};
use crate::shared::ecs::{CanCraft, CraftPartRequest, DragRequestEvent, Drill, Part, Player, PlayerStorage, SingleStorage, Temperature, ToggleDrillEvent};
use crate::shared::ecs::thruster::{Thruster, ThrusterOfPart};




@@ 59,14 60,13 @@ use crate::shared::ecs::thruster::{Thruster, ThrusterOfPart};
}*/

pub fn register_net(app: &mut App) {
    /*app
        .add_message::<ToClients<Hi>>()
        .add_message::<Hi>()
        .add_systems(Update, send_hi_to_client);*/
}
pub fn setup_net(app: &mut App) {
    app.insert_resource(MessageRegistry::default());
    app.add_systems(PostUpdate, recv_from_server);
    app
        .add_server_message::<Hi>()

        .add_client_message::<DragRequestEvent>()
        .add_client_message::<ToggleDrillEvent>()
        .add_client_message::<CraftPartRequest>()
        .add_client_message::<ThrustSolution>();
}

#[derive(Message, Deserialize, Serialize, TypePath, MapEntities)]


@@ 76,12 76,24 @@ pub struct Hi {
    pub time_offset: f64,
}

pub fn setup_net(app: &mut App) {
    app.insert_resource(ServerMessageRegistry::default());
    app.insert_resource(ClientMessageRegistry::default());
    app.add_systems(PostUpdate, recv_from_server);
    app.add_systems(PostUpdate, recv_from_client);
}
#[derive(Message, Deref, Deserialize, Serialize)]
pub struct ToClients<T: Message + TypePath> {
    #[deref]
    pub message: T,
    pub targets: SendTargets,
}
#[derive(Message, Deref, Deserialize, Serialize)]
pub struct FromClients<T: Message + TypePath> {
    pub client_id: ClientId,
    #[deref]
    pub message: T,
}

#[derive(Deserialize, Serialize)]
pub enum SendTargets {


@@ 96,10 108,15 @@ pub enum ClientId {
}

#[derive(Resource, Default)]
pub struct MessageRegistry {
pub struct ServerMessageRegistry {
    forward: HashMap<String, LaneIndex>,
    reverse: HashMap<LaneIndex, fn(Vec<u8>, &mut World)>,
}
#[derive(Resource, Default)]
pub struct ClientMessageRegistry {
    forward: HashMap<String, LaneIndex>,
    reverse: HashMap<LaneIndex, fn(Vec<u8>, ClientId, &mut World)>,
}

static COUNTER: AtomicU32 = AtomicU32::new(0);
fn get_lane_index() -> LaneIndex {


@@ 107,29 124,47 @@ fn get_lane_index() -> LaneIndex {
}

pub trait NetAppExt {
    fn add_server_message<T: Clone + Message + TypePath + Serialize + for<'a> Deserialize<'a>>(&mut self) -> &mut Self;
    fn add_server_message<T: Message + TypePath + Serialize + for<'a> Deserialize<'a>>(&mut self) -> &mut Self;
    fn add_client_message<T: Message + TypePath + Serialize + for<'a> Deserialize<'a>>(&mut self) -> &mut Self;
}
impl NetAppExt for App {
    fn add_server_message<T: Clone + Message + TypePath + Serialize + for<'a> Deserialize<'a>>(&mut self) -> &mut Self {
    fn add_server_message<T: Message + TypePath + Serialize + for<'a> Deserialize<'a>>(&mut self) -> &mut Self {
        self
            .add_message::<ToClients<T>>()
            .add_message::<T>()
            .add_systems(Startup, register_message::<T>)
            .add_systems(Startup, register_server_message::<T>)
            .add_systems(Update, send_to_client::<T>)
    }
    fn add_client_message<T: Message + TypePath + Serialize + for<'a> Deserialize<'a>>(&mut self) -> &mut Self {
        self
            .add_message::<FromClients<T>>()
            .add_message::<T>()
            .add_systems(Startup, register_client_message::<T>)
            .add_systems(Update, send_to_server::<T>)
    }
}
fn register_message<T: Message + TypePath + for<'a> Deserialize<'a>>(mut registry: ResMut<MessageRegistry>) {
fn register_server_message<T: Message + TypePath + for<'a> Deserialize<'a>>(mut registry: ResMut<ServerMessageRegistry>) {
    registry.forward.insert(T::type_path().to_string(), get_lane_index());
    registry.reverse.insert(get_lane_index(), |payload: Vec<u8>, world: &mut World| {
        let message = from_bytes::<T>(&payload).expect(&format!("Failed to deserialize message of type {}", T::type_path()));
        world.write_message(message).expect("Could not send message to game");
    });
}
fn register_client_message<T: Message + TypePath + for<'a> Deserialize<'a>>(mut registry: ResMut<ClientMessageRegistry>) {
    registry.forward.insert(T::type_path().to_string(), get_lane_index());
    registry.reverse.insert(get_lane_index(), |payload: Vec<u8>, client_id: ClientId, world: &mut World| {
        let message = from_bytes::<T>(&payload).expect(&format!("Failed to deserialize message of type {}", T::type_path()));
        world.write_message(FromClients {
            client_id,
            message,
        }).expect("Could not send message to game");
    });
}

fn send_to_client<M: Clone + Message + TypePath + Serialize>(
fn send_to_client<M: Message + TypePath + Serialize>(
    mut messages: MessageReader<ToClients<M>>,
    mut clients: Query<(Entity, &mut Transport), With<ChildOf>>,
    message_registry: Res<MessageRegistry>,
    message_registry: Res<ServerMessageRegistry>,
) {
    for message in messages.read() {
        match &message.targets {


@@ 158,12 193,28 @@ fn send_to_client<M: Clone + Message + TypePath + Serialize>(
        }
    }
}
fn send_to_server<M: Message + TypePath + Serialize>(
    mut messages: MessageReader<M>,
    mut sessions: Query<&mut Transport, Without<ChildOf>>,
    message_registry: Res<ClientMessageRegistry>,
) {
    for message in messages.read() {
        for mut transport in &mut sessions {
            transport.send.push(
                *message_registry.forward.get(M::type_path())
                    .expect("Failed to get message lane; the message likely isn't serialized yet"),
                to_allocvec(&message).expect("Failed to serialize message").into(),
                Instant::now(),
            ).expect("Failed to send message");
        }
    }
}
fn recv_from_server(
    world: &mut World
) {
    let mut system_state: SystemState<(
        Query<&mut Transport, Without<ChildOf>>,
        Res<MessageRegistry>,
        Res<ServerMessageRegistry>,
    )> = SystemState::new(world);
    let (mut sessions, message_registry) = system_state.get_mut(world);
    let mut messages = Vec::new();


@@ 181,3 232,26 @@ fn recv_from_server(
        message_fn(payload, world);
    }
}
fn recv_from_client(
    world: &mut World
) {
    let mut system_state: SystemState<(
        Query<(Entity, &mut Transport), With<ChildOf>>,
        Res<ClientMessageRegistry>,
    )> = SystemState::new(world);
    let (mut clients, message_registry) = system_state.get_mut(world);
    let mut messages = Vec::new();
    for (client_entity, mut transport) in clients.iter_mut() {
        for message in transport.recv.msgs.drain() {
            let payload = message.payload;
            let message_fn = message_registry.reverse.get(&message.lane).expect("Packet was sent across a lane that didn't have a message assigned to it yet");
            messages.push((payload, ClientId::Client(client_entity), *message_fn));
        }
        for _ in transport.recv.acks.drain() {

        }
    }
    for (payload, client_id, message_fn) in messages {
        message_fn(payload, client_id, world);
    }
}

M crates/unified/src/shared/plugins.rs => crates/unified/src/shared/plugins.rs +2 -5
@@ 1,6 1,6 @@
use aeronet_transport::AeronetTransportPlugin;
use crate::shared::ecs::{CraftPartRequest, DragRequestEvent, TimeOffset, ToggleDrillEvent};
use crate::shared::net::register_net;
use crate::shared::net::{register_net, setup_net};
use crate::shared::thrust::ThrustSolution;
use bevy::app::{App, PluginGroup, PluginGroupBuilder};
use bevy::diagnostic::DiagnosticsPlugin;


@@ 42,6 42,7 @@ impl PluginGroup for SharedPluginGroup {
            .add(physics_setup_plugin)
            //.add(register_replication)
            .add(register_everything)
            .add(setup_net)
            .add(register_net)
            .add(world_config_plugin)



@@ 54,10 55,6 @@ impl PluginGroup for SharedPluginGroup {
}

pub fn register_everything(app: &mut App) {
    app.add_message::<DragRequestEvent>();
    app.add_message::<ToggleDrillEvent>();
    app.add_message::<CraftPartRequest>();
    app.add_message::<ThrustSolution>();
}

fn physics_setup_plugin(app: &mut App) {

M crates/unified/src/shared/thrust.rs => crates/unified/src/shared/thrust.rs +3 -2
@@ 1,10 1,11 @@
use std::collections::BTreeSet;
use bevy::prelude::{Component, Entity, Message, Resource};
use bevy::{prelude::{Component, Entity, Message, Resource}, reflect::TypePath};
use serde::{Deserialize, Serialize};

/// A thrust solution, found by the thrust solver on the client.
/// `thrusters_on` is the set of thrusters that should be on.
/// Any thrusters not in this set should be off.
#[derive(Eq, PartialEq, Debug, Clone, Resource, Component, Message)]
#[derive(Eq, PartialEq, Debug, Clone, Resource, Component, Message, Serialize, Deserialize, TypePath)]
pub struct ThrustSolution {
    pub thrusters_on: BTreeSet<Entity>,
    pub converged: bool