use std::net::Ipv4Addr; use bevy::utils::tracing; use bevy::{ecs::event::ManualEventReader, prelude::*}; use bevy_twite::{twite::frame::MessageType, ServerEvent, TwiteServerConfig, TwiteServerPlugin}; use component::*; use packet::*; pub mod component; pub mod packet; pub mod macros; fn main() { let subscriber = tracing_subscriber::FmtSubscriber::new(); tracing::subscriber::set_global_default(subscriber).unwrap(); info!( "StarKingdoms server v{} starting up", env!("CARGO_PKG_VERSION") ); App::new() .insert_resource(TwiteServerConfig { addr: Ipv4Addr::new(0, 0, 0, 0), port: 3000 }) .add_plugins(MinimalPlugins) .add_plugins(TwiteServerPlugin) .add_systems(Startup, spawn_planets) //.add_systems(Update, on_connection) .add_systems(Update, on_message) .add_systems(Update, on_close) .add_systems(FixedUpdate, on_position_change) .run(); info!("Goodbye!"); } fn spawn_planets(mut commands: Commands) { info!("Spawning planets"); let earth_pos = Transform::from_xyz(0.0, 0.0, 0.0); commands.spawn(PlanetBundle { planet_type: PlanetType::Earth, transform: TransformBundle::from(earth_pos), }); } /*fn on_connection( mut commands: Commands, planet_query: Query<(Entity, &PlanetType, &Transform)>, mut reader: Local>, mut events: ResMut>, ) { let mut packets = Vec::new(); for ev in reader.read(&events) { info!("{:?}", ev); if let ServerEvent::Connection(addr) = ev { info!("client connected"); let _id = commands .spawn(PlayerBundle { part: PartBundle { part_type: PartType::Hearty, transform: TransformBundle::from(Transform::from_xyz(0.0, 0.0, 0.0)), }, addr: Player(*addr), }) .id() .index(); let mut planets = Vec::new(); for (entity, planet_type, transform) in planet_query.iter() { planets.push((entity.index(), Planet { planet_type: *planet_type, transform: proto_transform!(transform) })); } let packet = Packet::PlanetPositions { planets }; let buf = serde_json::to_vec(&packet).unwrap(); packets.push(ServerEvent::Send(*addr, MessageType::Text, buf)); } } for packet in packets { events.send(packet); } }*/ fn on_message( mut commands: Commands, planet_query: Query<(Entity, &PlanetType, &Transform)>, player_query: Query<(Entity, &Player)>, part_query: Query<(Entity, &PartType, &Transform)>, mut packet_recv: Local>, mut packet_send: ResMut>, ) { let mut packets = Vec::new(); for ev in packet_recv.read(&packet_send) { if let ServerEvent::Recv(addr, MessageType::Text, data) = ev { let data = String::from_utf8_lossy(&data); let json: serde_json::Value = err_or_cont!(serde_json::from_str(&data)); let packet_type = json["t"].clone(); let data = json["c"].clone(); let packet_type = some_or_cont!(packet_type.as_str()); match packet_type { // handshake "ClientLogin" => { // spawn player let username = data["username"].clone(); let username = some_or_cont!(username.as_str()); let transform = Transform::from_xyz(0.0, 0.0, 0.0); let id = commands .spawn(PlayerBundle { part: PartBundle { part_type: PartType::Hearty, transform: TransformBundle::from(transform), }, player: Player { addr: *addr, username: username.to_string() }, }).id().index(); // tell this player the planets let mut planets = Vec::new(); for (entity, planet_type, transform) in planet_query.iter() { planets.push((entity.index(), Planet { planet_type: *planet_type, transform: proto_transform!(transform) })); } let packet = Packet::PlanetPositions { planets }; let buf = serde_json::to_vec(&packet).unwrap(); packets.push(ServerEvent::Send(*addr, MessageType::Text, buf)); // tell the player already existing users let mut players = Vec::new(); for (entity, player) in &player_query { players.push((entity.index(), player.username.clone())); } let packet = Packet::PlayerList { players, }; let buf = serde_json::to_vec(&packet).unwrap(); packets.push(ServerEvent::Send(*addr, MessageType::Text, buf)); // tell other players that a player has spawned in let packet = Packet::SpawnPlayer { id, username: username.to_string(), }; let buf = serde_json::to_vec(&packet).unwrap(); packets.push(ServerEvent::Broadcast(MessageType::Text, buf)); // tell the player where parts are let mut parts = Vec::new(); for (entity, part_type, transform) in &part_query { parts.push((entity.index(), Part { part_type: *part_type, transform: proto_transform!(transform), })); } parts.push((id, Part { part_type: PartType::Hearty, transform: proto_transform!(transform), })); let packet = Packet::PartPositions { parts }; let buf = serde_json::to_vec(&packet).unwrap(); packets.push(ServerEvent::Send(*addr, MessageType::Text, buf)); } _ => continue }; } } for packet in packets { packet_send.send(packet); } } fn on_close( player_query: Query<(Entity, &Player)>, mut commands: Commands, mut packet_recv: Local>, mut packet_send: ResMut>, ) { let mut packets = Vec::new(); for packet in packet_recv.read(&packet_send) { if let ServerEvent::Close(addr) = packet { for (entity, player) in &player_query { if player.addr == *addr { commands.entity(entity).despawn(); let packet = Packet::PlayerLeave { id: entity.index() }; let buf = serde_json::to_vec(&packet).unwrap(); for (in_entity, player) in &player_query { if entity != in_entity { packets.push(ServerEvent::Send(player.addr, MessageType::Text, buf.clone())); } } } } } } for packet in packets { packet_send.send(packet); } } fn on_position_change( mut commands: Commands, part_query: Query<(Entity, &PartType, &Transform), Changed>, planet_query: Query<(Entity, &PlanetType, &Transform), Changed>, mut packet_send: EventWriter, ) { let mut updated_parts = Vec::new(); for (entity, part_type, transform) in part_query.iter() { let id = commands.entity(entity).id().index(); updated_parts.push((id, Part { part_type: *part_type, transform: proto_transform!(transform), })); } if !updated_parts.is_empty() { 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 = Vec::new(); for (entity, planet_type, transform) in planet_query.iter() { let id = commands.entity(entity).id().index(); planets.push((id, Planet { planet_type: *planet_type, transform: proto_transform!(transform) })); } if !planets.is_empty() { let packet = Packet::PlanetPositions { planets }; let buf = serde_json::to_vec(&packet).unwrap(); packet_send.send(ServerEvent::Broadcast(MessageType::Text, buf)); } }