use std::collections::HashMap;
use bevy_ecs::{
entity::Entity,
event::Events,
query::{QuerySingleError, With},
world::World,
};
use nalgebra::{Rotation2, Scale3, Translation3};
use starkingdoms_common::{packet::Packet, PartType, PlanetType};
use crate::components::{
Camera, Chat, Menu, Part, Player, PlayerResources, RecvPacket, SendPacket, ServerId,
SpriteBundle, Texture, Transform,
};
pub mod websocket;
fn texture_name(part_type: PartType, attached: bool) -> String {
use PartType::*;
if attached {
match part_type {
Placeholder => panic!("AHHHH PLACEHOLDER PANIC"),
Hearty => "hearty.svg",
Chassis => "chassis.svg",
Hub => "hub_on.svg",
LandingThruster => "landingthruster_on.svg",
LandingThrusterSuspension => "landingleg.svg",
}
.to_string()
} else {
match part_type {
Placeholder => panic!("AHHHH PLACEHOLDER PANIC"),
Hearty => "hearty.svg",
Chassis => "chassis.svg",
Hub => "hub_off.svg",
LandingThruster => "landingthruster_off.svg",
LandingThrusterSuspension => "landingleg.svg",
}
.to_string()
}
}
pub fn process_packets(
world: &mut World,
_send_packet_events: &mut Events<SendPacket>,
recv_packet_events: &mut Events<RecvPacket>,
planet_types: &mut HashMap<PlanetType, (Entity, u32)>,
) {
use Packet::*;
let mut recv_cursor = recv_packet_events.get_cursor();
for recv in recv_cursor.read(&recv_packet_events) {
match &recv.0 {
LoginResponse { id } => {
let mut player_query = world.query_filtered::<Entity, With<Player>>();
let entity = player_query.single(world);
world.entity_mut(entity).insert(ServerId(*id));
}
PlayerList { players } => {
// existing players
// username sync, eventually
for player in players {
world.spawn((
Transform {
translation: Translation3::new(0.0, 0.0, 0.0),
rotation: Rotation2::new(0.0),
scale: Scale3::new(25.0, 25.0, 1.0),
},
Texture {
name: "hearty.svg".to_string(),
},
ServerId(player.0),
Part(false),
));
}
}
SpawnPlayer { id, .. } => {
// username sync, eventually
world.spawn((
Transform {
translation: Translation3::new(0.0, 0.0, 0.0),
rotation: Rotation2::new(0.0),
scale: Scale3::new(25.0, 25.0, 1.0),
},
Texture {
name: "hearty.svg".to_string(),
},
ServerId(*id),
Part(false),
));
}
SpawnPart { id, part } => {
world.spawn((
Transform {
translation: Translation3::new(part.transform.x, part.transform.y, 0.0),
rotation: Rotation2::new(part.transform.rot),
scale: Scale3::new(25.0, 25.0, 1.0),
},
Texture {
name: texture_name(part.part_type, part.flags.attached),
},
ServerId(*id),
Part(part.flags.attached),
));
}
PartPositions { parts } => {
for (id, part) in parts {
if part.part_type == PartType::Hearty {
let mut player_query = world.query_filtered::<&ServerId, With<Player>>();
let server_id = match player_query.get_single(world) {
Ok(player) => player,
Err(e) => match e {
QuerySingleError::NoEntities(_) => {
continue;
}
QuerySingleError::MultipleEntities(_) => {
panic!("There should never multiple players marked as players");
}
},
};
if server_id.0 == *id {
let mut camera = world.resource_mut::<Camera>();
camera.x = -part.transform.x;
camera.y = -part.transform.y;
}
}
let mut part_query =
world
.query::<(Entity, &ServerId, &mut Transform, &mut Texture, &mut Part)>(
);
for (_, server_id, mut transform, mut texture, mut bevy_part) in
part_query.iter_mut(world)
{
if server_id.0 == *id {
transform.translation.x = part.transform.x;
transform.translation.y = part.transform.y;
transform.rotation = Rotation2::new(part.transform.rot);
if part.flags.attached && !bevy_part.0 {
texture.name = texture_name(part.part_type, part.flags.attached);
bevy_part.0 = true;
} else if !part.flags.attached && bevy_part.0 {
texture.name = texture_name(part.part_type, part.flags.attached);
bevy_part.0 = false;
}
}
}
}
}
PlanetPositions { planets } => {
for (server_id, planet) in planets {
if !planet_types.contains_key(&planet.planet_type) {
let entity = world.spawn(SpriteBundle {
transform: Transform {
translation: Translation3::new(
planet.transform.x,
planet.transform.y,
0.0,
),
rotation: Rotation2::new(planet.transform.rot),
scale: Scale3::new(planet.radius, planet.radius, 1.0),
},
texture: Texture {
name: match planet.planet_type {
/*PlanetType::Sun => "sun.svg",
PlanetType::Mercury => "mercury.svg",
PlanetType::Venus => "venus.svg",
PlanetType::Earth => "earth.svg",
PlanetType::Moon => "moon.svg",
PlanetType::Mars => "mars.svg",
PlanetType::Jupiter => "jupiter.svg",
PlanetType::Saturn => "saturn.svg",
PlanetType::Uranus => "uranus.svg",
PlanetType::Neptune => "neptune.svg",
PlanetType::Pluto => "pluto.svg",*/
PlanetType::Sun => "sun.svg",
PlanetType::Mercury => "moon.svg",
PlanetType::Venus => "venus.svg",
PlanetType::Earth => "earth.svg",
PlanetType::Moon => "moon.svg",
PlanetType::Mars => "mars.svg",
PlanetType::Jupiter => "jupiter.svg",
PlanetType::Saturn => "sun.svg",
PlanetType::Uranus => "venus.svg",
PlanetType::Neptune => "mars.svg",
PlanetType::Pluto => "earth.svg",
}
.to_string(),
},
});
planet_types.insert(planet.planet_type, (entity.id(), *server_id));
}
}
}
EnergyUpdate { amount, max } => {
let mut r = world.resource_mut::<PlayerResources>();
r.fuel_amount = *amount;
r.fuel_max = *max;
}
OpenCraftingUi { id } => {
let mut query = world.query::<(Entity, &ServerId)>();
let mut matching_id = None;
for (entity, server_id) in query.iter(world) {
if server_id.0 == *id {
matching_id = Some(entity);
}
}
if let Some(id) = matching_id {
world.entity_mut(id).insert(Menu);
}
}
Message { actor, content, .. } => {
let mut chat = world.get_resource_mut::<Chat>().unwrap();
chat.messages
.push(format!("{}: {}", actor.clone(), content.clone()));
}
PlayerLeave { id } => {
let mut part_query = world.query_filtered::<(Entity, &ServerId), With<Part>>();
let mut entity_to_remove = None;
for (entity, server_id) in part_query.iter_mut(world) {
if server_id.0 == *id {
entity_to_remove = Some(entity);
}
}
match entity_to_remove {
Some(entity) => {
world.despawn(entity);
}
None => {}
}
}
DespawnPart { id } => {
let mut part_query = world.query_filtered::<(Entity, &ServerId), With<Part>>();
let mut entity_to_remove = None;
for (entity, server_id) in part_query.iter_mut(world) {
if server_id.0 == *id {
entity_to_remove = Some(entity);
}
}
match entity_to_remove {
Some(entity) => {
world.despawn(entity);
}
None => {}
}
}
_ => {}
}
}
}