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
+}