use std::collections::HashMap;
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;
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 { port: 3000 })
.add_plugins(MinimalPlugins)
.add_plugins(TwiteServerPlugin)
.add_systems(Startup, spawn_planets)
.add_systems(FixedUpdate, on_connection)
.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<ManualEventReader<ServerEvent>>,
mut events: ResMut<Events<ServerEvent>>,
) {
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 = HashMap::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),
},
);
}
let packet = PlanetPositionPacket { 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_position_change(
mut commands: Commands,
part_query: Query<(Entity, &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 id = commands.entity(entity).id().index();
let translation = transform.translation;
updated_parts.insert(id, (0, translation.x, translation.y)); // Type hearty = 0
}
if !updated_parts.is_empty() {
let packet = PartPositionPacket { parts: updated_parts };
let buf = serde_json::to_vec(&packet).unwrap();
packet_send.send(ServerEvent::Broadcast(MessageType::Text, buf));
}
let mut planets = HashMap::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),
},
);
}
if !planets.is_empty() {
let packet = PlanetPositionPacket { planets };
let buf = serde_json::to_vec(&packet).unwrap();
packet_send.send(ServerEvent::Broadcast(MessageType::Text, buf));
}
}