~starkingdoms/starkingdoms

1e3bba3be59969d7b0a8c8eb3fe8a21f43d8711b — core 2 years ago c0d7ff2
redo whole protocol, client does something, old client gone
M server/src/component.rs => server/src/component.rs +3 -2
@@ 1,13 1,14 @@
use std::net::SocketAddr;

use bevy::prelude::*;
use serde::{Deserialize, Serialize};

#[derive(Component, Clone, Copy)]
#[derive(Component, Clone, Copy, Serialize, Deserialize, Debug)]
pub enum PlanetType {
    Earth,
}

#[derive(Component, Clone, Copy)]
#[derive(Component, Clone, Copy, Serialize, Deserialize, Debug)]
pub enum PartType {
    Hearty,
}

M server/src/main.rs => server/src/main.rs +21 -28
@@ 1,5 1,3 @@
use std::collections::HashMap;

use bevy::utils::tracing;
use bevy::{ecs::event::ManualEventReader, prelude::*};
use bevy_twite::{twite::frame::MessageType, ServerEvent, TwiteServerConfig, TwiteServerPlugin};


@@ 22,7 20,7 @@ fn main() {
        .add_plugins(MinimalPlugins)
        .add_plugins(TwiteServerPlugin)
        .add_systems(Startup, spawn_planets)
        .add_systems(FixedUpdate, on_connection)
        .add_systems(Update, on_connection)
        .add_systems(FixedUpdate, on_position_change)
        .run();



@@ 60,18 58,15 @@ fn on_connection(
                .id()
                .index();

            let mut planets = HashMap::new();
            let mut planets = Vec::new();
            for (entity, planet_type, transform) in planet_query.iter() {
                planets.insert(
                    entity.index(),
                    PacketPlanet {
                        planet_type: *planet_type as u8,
                        position: (transform.translation.x, transform.translation.y),
                    },
                );
                planets.push((entity.index(), Planet {
                    planet_type: *planet_type,
                    transform: proto_transform!(transform)
                }));
            }

            let packet = PlanetPositionPacket { planets };
            let packet = Packet::PlanetPositions { planets };
            let buf = serde_json::to_vec(&packet).unwrap();

            packets.push(ServerEvent::Send(*addr, MessageType::Text, buf));


@@ 84,39 79,37 @@ fn on_connection(

fn on_position_change(
    mut commands: Commands,
    part_query: Query<(Entity, &Transform), (With<Player>, Changed<Transform>)>,
    part_query: Query<(Entity, &PartType, &Transform), (With<Player>, Changed<Transform>)>,
    planet_query: Query<(Entity, &PlanetType, &Transform), Changed<Transform>>,
    mut packet_send: EventWriter<ServerEvent>,
) {
    let mut updated_parts = HashMap::new();
    for (entity, transform) in part_query.iter() {
    let mut updated_parts = Vec::new();
    for (entity, part_type, transform) in part_query.iter() {
        let id = commands.entity(entity).id().index();
        let translation = transform.translation;
        updated_parts.insert(id, (0, translation.x, translation.y)); // Type hearty = 0
        updated_parts.push((id, Part {
            part_type: *part_type,
            transform: proto_transform!(transform),
        }));
    }

    if !updated_parts.is_empty() {
        let packet = PartPositionPacket { parts: updated_parts };
        let packet = Packet::PartPositions { parts: updated_parts };
        let buf = serde_json::to_vec(&packet).unwrap();

        packet_send.send(ServerEvent::Broadcast(MessageType::Text, buf));
    }

    let mut planets = HashMap::new();
    let mut planets = Vec::new();
    for (entity, planet_type, transform) in planet_query.iter() {
        let id = commands.entity(entity).id().index();
        let translation = transform.translation;
        planets.insert(
            id,
            PacketPlanet {
                planet_type: *planet_type as u8,
                position: (translation.x, translation.y),
            },
        );
        planets.push((id, Planet {
            planet_type: *planet_type,
            transform: proto_transform!(transform)
        }));
    }

    if !planets.is_empty() {
        let packet = PlanetPositionPacket { planets };
        let packet = Packet::PlanetPositions { planets };
        let buf = serde_json::to_vec(&packet).unwrap();

        packet_send.send(ServerEvent::Broadcast(MessageType::Text, buf));

M server/src/packet.rs => server/src/packet.rs +44 -20
@@ 1,26 1,50 @@
use std::collections::HashMap;
use serde::{Deserialize, Serialize};
use crate::component::{PartType, PlanetType};

use serde::Serialize;

#[derive(Debug, Serialize)]
pub struct SpawnPlayer {
    pub id: u32,
    pub username: String,
    pub position: (f32, f32),
#[derive(Debug, Serialize, Deserialize)]
pub struct ProtoTransform {
    pub x: f32,
    pub y: f32,
    pub rot: f32
}

#[derive(Debug, Serialize)]
pub struct PacketPlanet {
    pub planet_type: u8,
    pub position: (f32, f32),
#[macro_export]
macro_rules! proto_transform {
    ($e:expr) => {
        $crate::packet::ProtoTransform {
            x: $e.translation.x,
            y: $e.translation.y,
            rot: $e.rotation.to_euler(bevy::math::EulerRot::ZYX).0
        }
    };
}

#[derive(Debug, Serialize)]
pub struct PlanetPositionPacket {
    pub planets: HashMap<u32, PacketPlanet>, // id, (Type, x, y)
#[derive(Debug, Serialize, Deserialize)]
pub struct Planet {
    pub planet_type: PlanetType,
    pub transform: ProtoTransform
}

#[derive(Debug, Serialize)]
pub struct PartPositionPacket {
    pub parts: HashMap<u32, (u8, f32, f32)>, // id, (Type, x, y)
#[derive(Debug, Serialize, Deserialize)]
pub struct Part {
    pub part_type: PartType,
    pub transform: ProtoTransform
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "t", content = "c")]
pub enum Packet {
    ClientLogin {
        username: String,
        jwt: Option<String>,
    },
    SpawnPlayer {
        id: u32,
        username: String,
        position: ProtoTransform
    },
    PlanetPositions {
        planets: Vec<(u32, Planet)>
    },
    PartPositions {
        parts: Vec<(u32, Part)>
    }
}
\ No newline at end of file

M starkingdoms-client/src/gateway.ts => starkingdoms-client/src/gateway.ts +13 -2
@@ 1,4 1,5 @@
import createDebug from "debug";
import {Packet, PacketType} from "./protocol.ts";

const logger = createDebug("gateway");



@@ 6,7 7,7 @@ export interface GatewayClient {
    socket: WebSocket;
}

export async function gateway_connect(url: string) {
export async function gateway_connect(url: string, username: string) {
    logger("connecting to gateway socket at " + url)

    let ws = await _websocket_connect(url);


@@ 17,8 18,18 @@ export async function gateway_connect(url: string) {
        socket: ws
    };

    let packet: Packet = {
        t: PacketType.ClientLogin,
        c: {
            username,
            jwt: null
        }
    };
    ws.send(JSON.stringify(packet));

    ws.onmessage = (e) => {
        console.log(e.data);
        let packet: Packet = JSON.parse(e.data);
        logger(packet);
    }

    return client;

A starkingdoms-client/src/protocol.ts => starkingdoms-client/src/protocol.ts +46 -0
@@ 0,0 1,46 @@
export interface ProtoTransform {
    x: number,
    y: number,
    rot: number
}
export enum PlanetType {
    Earth = "Earth"
}
export enum PartType {
    Hearty = "Hearty"
}
export interface Planet {
    planet_type: PlanetType,
    transform: ProtoTransform
}
export interface Part {
    part_type: PartType,
    transform: ProtoTransform
}
export interface ClientLoginPacket {
    username: string,
    jwt: string | null,
}
export interface SpawnPlayerPacket {
    id: number,
    username: string,
    position: ProtoTransform
}
export interface PlanetPositionsPacket {
    planets: [number, Planet][]
}
export interface PartPositionsPacket {
    parts: [number, Part][]
}

export enum PacketType {
    ClientLogin = "ClientLogin",
    SpawnPlayer = "SpawnPlayer",
    PlanetPositions = "PlanetPositions",
    PartPositions = "PartPositions"
}

export interface Packet {
    t: PacketType,
    c: ClientLoginPacket | SpawnPlayerPacket | PlanetPositionsPacket | PartPositionsPacket
}