M Cargo.lock => Cargo.lock +1 -0
@@ 7658,6 7658,7 @@ dependencies = [
"console_error_panic_hook",
"getrandom 0.3.3",
"log",
+ "ordered-float 5.0.0",
"rand 0.9.1",
"serde",
"tracing-subscriber",
M crates/unified/Cargo.toml => crates/unified/Cargo.toml +2 -0
@@ 51,6 51,8 @@ aeronet_websocket = { version = "0.14", features = ["client"] }
bevy_enoki = "0.4"
+ordered-float = "5"
+
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
[target.'cfg(target_arch = "wasm32")'.dependencies]
M crates/unified/assets/config/planets.pc.toml => crates/unified/assets/config/planets.pc.toml +3 -0
@@ 22,6 22,7 @@ default_transform = [216_999.6, 0.0, 0.0]
[[planets]]
name = "Earth"
sprite = "textures/earth.png"
+indicator_sprite = "textures/earth_icon.png"
radius = 1000.0 # m
mass = 10_000.0 # kg
default_transform = [300_000.0, 0.0, 0.0]
@@ 29,6 30,7 @@ default_transform = [300_000.0, 0.0, 0.0]
[[planets]]
name = "Moon"
sprite = "textures/moon.png"
+indicator_sprite = "textures/moon_icon.png"
radius = 272.7 # m
mass = 123.082_143_245 # kg
default_transform = [301_541.4, 0.0, 0.0]
@@ 36,6 38,7 @@ default_transform = [301_541.4, 0.0, 0.0]
[[planets]]
name = "Mars"
sprite = "textures/mars.png"
+indicator_sprite = "textures/mars_icon.png"
radius = 531.0 # m
mass = 1_070.519_602 # kg
default_transform = [457_100.0, 0.0, 0.0]
M crates/unified/src/client/mod.rs => crates/unified/src/client/mod.rs +4 -3
@@ 1,15 1,15 @@
mod colors;
mod incoming_particles;
mod incoming_parts;
-mod incoming_planets;
mod key_input;
mod net;
mod starfield;
mod ui;
+mod planet;
use crate::client::incoming_particles::replicated_particles_plugin;
use crate::client::incoming_parts::incoming_parts_plugin;
-use crate::client::incoming_planets::incoming_planets_plugin;
+use planet::incoming_planets::incoming_planets_plugin;
use crate::client::key_input::key_input_plugin;
use crate::client::starfield::starfield_plugin;
use crate::client::ui::ui_plugin;
@@ 19,6 19,7 @@ use bevy::core_pipeline::fxaa::Fxaa;
use bevy::prelude::*;
use bevy::window::PrimaryWindow;
use bevy_replicon::shared::server_entity_map::ServerEntityMap;
+use crate::client::planet::indicators::indicators_plugin;
pub struct ClientPlugin {
pub server: String,
@@ 41,7 42,7 @@ impl Plugin for ClientPlugin {
.add_systems(Update, update_cursor_position)
.add_systems(Update, follow_camera)
.add_systems(Update, find_me)
- .add_plugins(incoming_planets_plugin)
+ .add_plugins((incoming_planets_plugin, indicators_plugin))
.add_plugins(incoming_parts_plugin)
.add_plugins(key_input_plugin)
.add_plugins(starfield_plugin)
R crates/unified/src/client/incoming_planets.rs => crates/unified/src/client/planet/incoming_planets.rs +0 -0
A crates/unified/src/client/planet/indicators.rs => crates/unified/src/client/planet/indicators.rs +65 -0
@@ 0,0 1,65 @@
+use bevy::prelude::*;
+use bevy::window::PrimaryWindow;
+use ordered_float::OrderedFloat;
+use crate::client::Me;
+use crate::config::planet::Planet;
+
+pub fn indicators_plugin(app: &mut App) {
+ app.add_systems(PreUpdate, (add_indicators, update_indicators))
+ .add_systems(Update, update_indicators_position);
+}
+
+#[derive(Component)]
+struct PlanetIndicator(String);
+#[derive(Component)]
+struct HasIndicator(Entity);
+
+fn add_indicators(planets_wo_indicators: Query<(Entity, &Planet), Without<HasIndicator>>, player: Query<Entity, With<Me>>, asset_server: Res<AssetServer>, mut commands: Commands) {
+ let Ok(me) = player.single() else { return; };
+ for (planet, planet_data) in &planets_wo_indicators {
+ let Some(indicator_url) = &planet_data.indicator_sprite else { continue };
+ let mut sprite = Sprite::from_image(asset_server.load(indicator_url));
+ sprite.custom_size = Some(Vec2::new(50.0, 50.0));
+ let indicator = commands.spawn((
+ ChildOf(me),
+ PlanetIndicator(planet_data.name.clone()),
+ sprite,
+ Transform::from_xyz(0.0, 0.0, 0.0)
+ )).id();
+ commands.entity(planet).insert(HasIndicator(indicator));
+ }
+}
+fn update_indicators(changed_planets_w_indicators: Query<(&Planet, &HasIndicator), Changed<Planet>>, asset_server: Res<AssetServer>, mut commands: Commands) {
+ for (planet_data, indicator) in changed_planets_w_indicators.iter() {
+ let Some(indicator_sprite) = &planet_data.indicator_sprite else { continue; };
+ let mut sprite = Sprite::from_image(asset_server.load(indicator_sprite));
+ sprite.custom_size = Some(Vec2::new(50.0, 50.0));
+ commands.entity(indicator.0)
+ .remove::<Sprite>()
+ .insert(sprite);
+ }
+}
+fn update_indicators_position(
+ planets_w_indicator: Query<(&Transform, &HasIndicator), Without<PlanetIndicator>>,
+ player: Query<&Transform, (With<Me>, Without<PlanetIndicator>)>,
+ mut indicators: Query<(&mut Transform), (With<PlanetIndicator>, Without<HasIndicator>, Without<Me>)>,
+ window: Query<&Window, With<PrimaryWindow>>,
+)
+{
+ let Ok(player_position) = player.single() else { return; };
+ let window = window.single().unwrap();
+
+ for (planet_position, indicator_id) in &planets_w_indicator {
+ let mut offset = planet_position.translation - player_position.translation;
+ let half_window_height = window.height() / 2.0 - 25.0;
+ let half_window_width = window.width() / 2.0 - 25.0;
+ offset.x = offset.x.clamp(-half_window_width, half_window_width);
+ offset.y = offset.y.clamp(-half_window_height, half_window_height);
+
+ let Ok(mut this_indicator) = indicators.get_mut(indicator_id.0) else { continue; };
+
+ let inv_rot = player_position.rotation.inverse();
+ this_indicator.translation = inv_rot.mul_vec3(Vec3::new(offset.x, offset.y, 0.0));
+ this_indicator.rotation = inv_rot;
+ }
+}<
\ No newline at end of file
A crates/unified/src/client/planet/mod.rs => crates/unified/src/client/planet/mod.rs +2 -0
@@ 0,0 1,2 @@
+pub mod incoming_planets;
+pub mod indicators;<
\ No newline at end of file
M crates/unified/src/config/planet.rs => crates/unified/src/config/planet.rs +1 -0
@@ 8,6 8,7 @@ use serde::{Deserialize, Serialize};
pub struct Planet {
pub name: String,
pub sprite: String,
+ pub indicator_sprite: Option<String>,
pub radius: f32,
pub mass: f32,
pub default_transform: [f32; 3],
M crates/unified/src/server/player.rs => crates/unified/src/server/player.rs +4 -4
@@ 81,7 81,7 @@ fn handle_new_players(
(
Particles {
effect: "particles/ship_thruster.particle.ron".to_string(),
- active: true
+ active: false
},
Transform::from_xyz(
-wc.part.default_width / 2.0 + 5.0,
@@ 95,7 95,7 @@ fn handle_new_players(
(
Particles {
effect: "particles/ship_thruster.particle.ron".to_string(),
- active: true
+ active: false
},
Transform::from_xyz(
wc.part.default_width / 2.0 - 5.0,
@@ 109,7 109,7 @@ fn handle_new_players(
(
Particles {
effect: "particles/ship_thruster.particle.ron".to_string(),
- active: true
+ active: false
},
Transform::from_xyz(
-wc.part.default_width / 2.0 + 5.0,
@@ 122,7 122,7 @@ fn handle_new_players(
(
Particles {
effect: "particles/ship_thruster.particle.ron".to_string(),
- active: true
+ active: false
},
Transform::from_xyz(
wc.part.default_width / 2.0 - 5.0,