diff --git a/cosmos_client/src/inventory/mod.rs b/cosmos_client/src/inventory/mod.rs index 7c5e923bc..d29375964 100644 --- a/cosmos_client/src/inventory/mod.rs +++ b/cosmos_client/src/inventory/mod.rs @@ -631,6 +631,7 @@ fn handle_interactions( fn create_item_stack_slot_data(item_stack: &ItemStack, ecmds: &mut EntityCommands, text_style: TextStyle, quantity: u16) { ecmds .insert(( + Name::new("Render Item"), NodeBundle { style: Style { width: Val::Px(64.0), diff --git a/cosmos_client/src/netty/gameplay/receiver.rs b/cosmos_client/src/netty/gameplay/receiver.rs index 111b4f730..d5d60f2de 100644 --- a/cosmos_client/src/netty/gameplay/receiver.rs +++ b/cosmos_client/src/netty/gameplay/receiver.rs @@ -309,6 +309,7 @@ pub(crate) fn client_sync_players( }, Collider::capsule_y(0.5, 0.25), LockedAxes::ROTATION_LOCKED, + Name::new(format!("Player ({name})")), RigidBody::Dynamic, body.create_velocity(), Player::new(name, id), diff --git a/cosmos_client/src/ui/crosshair.rs b/cosmos_client/src/ui/crosshair.rs index fd25ceafe..3e1b1399a 100644 --- a/cosmos_client/src/ui/crosshair.rs +++ b/cosmos_client/src/ui/crosshair.rs @@ -7,19 +7,22 @@ use crate::state::game_state::GameState; fn add_crosshair(mut commands: Commands, asset_server: Res) { commands - .spawn(NodeBundle { - style: Style { - position_type: PositionType::Absolute, - display: Display::Flex, - justify_content: JustifyContent::Center, - align_items: AlignItems::Center, - width: Val::Percent(100.0), - height: Val::Percent(100.0), + .spawn(( + NodeBundle { + style: Style { + position_type: PositionType::Absolute, + display: Display::Flex, + justify_content: JustifyContent::Center, + align_items: AlignItems::Center, + width: Val::Percent(100.0), + height: Val::Percent(100.0), + ..default() + }, + // color: Color::NONE.into(), ..default() }, - // color: Color::NONE.into(), - ..default() - }) + Name::new("Crosshair"), + )) .with_children(|parent| { parent .spawn(ImageBundle { diff --git a/cosmos_client/src/ui/item_renderer/mod.rs b/cosmos_client/src/ui/item_renderer/mod.rs index c38d54553..3121ab74a 100644 --- a/cosmos_client/src/ui/item_renderer/mod.rs +++ b/cosmos_client/src/ui/item_renderer/mod.rs @@ -26,6 +26,7 @@ struct UICamera; fn create_ui_camera(mut commands: Commands) { commands.spawn(( + Name::new("UI Camera"), Camera3dBundle { projection: Projection::Orthographic(OrthographicProjection { scaling_mode: ScalingMode::WindowSize(40.0), diff --git a/cosmos_core/src/structure/mod.rs b/cosmos_core/src/structure/mod.rs index bb8b118f5..a1e92de1b 100644 --- a/cosmos_core/src/structure/mod.rs +++ b/cosmos_core/src/structure/mod.rs @@ -4,7 +4,7 @@ use std::fmt::Display; -use bevy::prelude::{App, Event, IntoSystemConfigs, PreUpdate}; +use bevy::prelude::{App, Event, IntoSystemConfigs, Name, PreUpdate}; use bevy::reflect::Reflect; use bevy::utils::{HashMap, HashSet}; use bevy_rapier3d::prelude::PhysicsWorld; @@ -509,6 +509,43 @@ fn remove_empty_chunks( } } +fn spawn_chunk_entity( + commands: &mut Commands, + structure: &mut Structure, + chunk_coordinate: ChunkCoordinate, + structure_entity: Entity, + body_world: Option<&PhysicsWorld>, + chunk_set_events: &mut HashSet, +) { + let mut entity_cmds = commands.spawn(( + PbrBundle { + transform: Transform::from_translation(structure.chunk_relative_position(chunk_coordinate)), + ..Default::default() + }, + Name::new("Chunk Entity"), + NoSendEntity, + ChunkEntity { + structure_entity, + chunk_location: chunk_coordinate, + }, + )); + + if let Some(bw) = body_world { + entity_cmds.insert(*bw); + } + + let entity = entity_cmds.id(); + + commands.entity(structure_entity).add_child(entity); + + structure.set_chunk_entity(chunk_coordinate, entity); + + chunk_set_events.insert(ChunkSetEvent { + structure_entity, + coords: chunk_coordinate, + }); +} + fn add_chunks_system( mut chunk_init_reader: EventReader, mut block_reader: EventReader, @@ -532,37 +569,23 @@ fn add_chunks_system( } for (structure_entity, chunk_coordinate) in s_chunks { - if let Ok((mut structure, body_world)) = structure_query.get_mut(structure_entity) { - if let Some(chunk) = structure.chunk_from_chunk_coordinates(chunk_coordinate) { - if !chunk.is_empty() && structure.chunk_entity(chunk_coordinate).is_none() { - let mut entity_cmds = commands.spawn(( - PbrBundle { - transform: Transform::from_translation(structure.chunk_relative_position(chunk_coordinate)), - ..Default::default() - }, - NoSendEntity, - ChunkEntity { - structure_entity, - chunk_location: chunk_coordinate, - }, - )); - - if let Some(bw) = body_world { - entity_cmds.insert(*bw); - } - - let entity = entity_cmds.id(); - - commands.entity(structure_entity).add_child(entity); - - structure.set_chunk_entity(chunk_coordinate, entity); - - chunk_set_events.insert(ChunkSetEvent { - structure_entity, - coords: chunk_coordinate, - }); - } - } + let Ok((mut structure, body_world)) = structure_query.get_mut(structure_entity) else { + continue; + }; + + let Some(chunk) = structure.chunk_from_chunk_coordinates(chunk_coordinate) else { + continue; + }; + + if !chunk.is_empty() && structure.chunk_entity(chunk_coordinate).is_none() { + spawn_chunk_entity( + &mut commands, + &mut structure, + chunk_coordinate, + structure_entity, + body_world, + &mut chunk_set_events, + ); } } diff --git a/cosmos_server/src/events/netty/netty_events.rs b/cosmos_server/src/events/netty/netty_events.rs index 41aa11e0e..8c16f6d5a 100644 --- a/cosmos_server/src/events/netty/netty_events.rs +++ b/cosmos_server/src/events/netty/netty_events.rs @@ -125,6 +125,7 @@ fn handle_events_system( PlayerLooking { rotation: Quat::IDENTITY }, LoadingDistance::new(2, 9999), ActiveEvents::COLLISION_EVENTS, + Name::new(format!("Player ({name})")), )); let entity = player_commands.id(); diff --git a/cosmos_server/src/persistence/mod.rs b/cosmos_server/src/persistence/mod.rs index 2a6b4d37c..1544370f0 100644 --- a/cosmos_server/src/persistence/mod.rs +++ b/cosmos_server/src/persistence/mod.rs @@ -271,7 +271,7 @@ impl SerializedData { } /// Returns true if a sector has at some point been generated at this location -pub fn is_sector_loaded(sector: Sector) -> bool { +pub fn is_sector_generated(sector: Sector) -> bool { fs::try_exists(SaveFileIdentifier::get_sector_path(sector)).unwrap_or(false) } diff --git a/cosmos_server/src/persistence/player_loading.rs b/cosmos_server/src/persistence/player_loading.rs index 304088126..d9facf8e9 100644 --- a/cosmos_server/src/persistence/player_loading.rs +++ b/cosmos_server/src/persistence/player_loading.rs @@ -3,7 +3,7 @@ use std::{ffi::OsStr, fs, time::Duration}; use bevy::{ - prelude::{warn, App, Commands, Component, DespawnRecursiveExt, Entity, IntoSystemConfigs, Query, ResMut, Update, With, Without}, + prelude::{warn, App, Commands, Component, DespawnRecursiveExt, Entity, IntoSystemConfigs, Name, Query, ResMut, Update, With, Without}, tasks::{AsyncComputeTaskPool, Task}, time::common_conditions::on_timer, }; @@ -62,7 +62,7 @@ fn monitor_loading_task( .entity_id() .expect("A non-base SaveFileIdentifier was attempted to be loaded in load_near") }) { - commands.spawn((sfi, NeedsLoaded)); + commands.spawn((sfi, NeedsLoaded, Name::new("Needs Loaded Entity"))); } } } diff --git a/cosmos_server/src/structure/asteroid/mod.rs b/cosmos_server/src/structure/asteroid/mod.rs index 3519a6aa6..fda780321 100644 --- a/cosmos_server/src/structure/asteroid/mod.rs +++ b/cosmos_server/src/structure/asteroid/mod.rs @@ -3,10 +3,12 @@ use bevy::prelude::App; mod generator; +mod persistence; pub mod server_asteroid_builder; mod sync; pub(super) fn register(app: &mut App) { sync::register(app); generator::register(app); + persistence::register(app); } diff --git a/cosmos_server/src/structure/asteroid/persistence.rs b/cosmos_server/src/structure/asteroid/persistence.rs new file mode 100644 index 000000000..7491a507b --- /dev/null +++ b/cosmos_server/src/structure/asteroid/persistence.rs @@ -0,0 +1,103 @@ +use bevy::prelude::*; +use cosmos_core::structure::{ + asteroid::{asteroid_builder::TAsteroidBuilder, Asteroid}, + events::StructureLoadedEvent, + structure_iterator::ChunkIteratorResult, + ChunkInitEvent, Structure, +}; + +use crate::persistence::{ + loading::{begin_loading, done_loading, NeedsLoaded}, + saving::{begin_saving, done_saving, NeedsSaved}, + SerializedData, +}; + +use super::server_asteroid_builder::ServerAsteroidBuilder; + +fn on_save_structure(mut query: Query<(&mut SerializedData, &Structure), (With, With)>) { + for (mut s_data, structure) in query.iter_mut() { + s_data.serialize_data("cosmos:structure", structure); + s_data.serialize_data("cosmos:is_asteroid", &true); + } +} + +fn on_load_structure( + query: Query<(Entity, &SerializedData), With>, + mut event_writer: EventWriter, + mut commands: Commands, +) { + for (entity, s_data) in query.iter() { + if s_data.deserialize_data::("cosmos:is_asteroid").unwrap_or(false) { + if let Some(mut structure) = s_data.deserialize_data::("cosmos:structure") { + let loc = s_data + .deserialize_data("cosmos:location") + .expect("Every asteroid should have a location when saved!"); + + let mut entity_cmd = commands.entity(entity); + + let builder = ServerAsteroidBuilder::default(); + + builder.insert_asteroid(&mut entity_cmd, loc, &mut structure); + + let entity = entity_cmd.id(); + + event_writer.send(DelayedStructureLoadEvent(entity)); + + commands.entity(entity).insert(structure); + } + } + } +} + +/// I hate this, but the only way to prevent issues with events is to delay the sending of the chunk init events +/// by 2 frames, so two events are needed to do this. This is really horrible, but the only way I can think of +/// to get this to work ;( +#[derive(Debug, Event)] +struct DelayedStructureLoadEvent(pub Entity); +#[derive(Debug, Event)] +struct EvenMoreDelayedStructureLoadEvent(Entity); + +fn delayed_structure_event( + mut event_reader: EventReader, + mut event_writer: EventWriter, +) { + for ev in event_reader.iter() { + event_writer.send(EvenMoreDelayedStructureLoadEvent(ev.0)); + } +} + +fn even_more_delayed_structure_event( + mut event_reader: EventReader, + mut chunk_set_event_writer: EventWriter, + mut structure_loaded_event_writer: EventWriter, + query: Query<&Structure>, +) { + for ev in event_reader.iter() { + if let Ok(structure) = query.get(ev.0) { + for res in structure.all_chunks_iter(false) { + // This will always be true because include_empty is false + if let ChunkIteratorResult::FilledChunk { + position: coords, + chunk: _, + } = res + { + chunk_set_event_writer.send(ChunkInitEvent { + structure_entity: ev.0, + coords, + }); + } + } + } + + structure_loaded_event_writer.send(StructureLoadedEvent { structure_entity: ev.0 }); + } +} + +pub(super) fn register(app: &mut App) { + app.add_systems(PreUpdate, even_more_delayed_structure_event) + .add_systems(Update, delayed_structure_event) + .add_event::() + .add_event::() + .add_systems(First, on_save_structure.after(begin_saving).before(done_saving)) + .add_systems(Update, on_load_structure.after(begin_loading).before(done_loading)); +} diff --git a/cosmos_server/src/structure/planet/persistence.rs b/cosmos_server/src/structure/planet/persistence.rs index 8d304b2e8..11b055805 100644 --- a/cosmos_server/src/structure/planet/persistence.rs +++ b/cosmos_server/src/structure/planet/persistence.rs @@ -126,6 +126,7 @@ fn populate_chunks( .insert(( serialized_data, NeedsLoaded, + Name::new("Needs Loaded Chunk"), NoSendEntity, ChunkEntity { structure_entity: needs.structure_entity, @@ -137,10 +138,13 @@ fn populate_chunks( } else { commands .entity(entity) - .insert(ChunkNeedsGenerated { - coords: needs.chunk_coords, - structure_entity: needs.structure_entity, - }) + .insert(( + ChunkNeedsGenerated { + coords: needs.chunk_coords, + structure_entity: needs.structure_entity, + }, + Name::new("Needs Generated Chunk"), + )) .remove::(); } } @@ -157,10 +161,11 @@ fn load_chunk( if let Ok(mut structure) = structure_query.get_mut(ce.structure_entity) { let coords = chunk.chunk_coordinates(); - commands.entity(entity).insert(PbrBundle { - transform: Transform::from_translation(structure.chunk_relative_position(coords)), - ..Default::default() - }); + commands + .entity(entity) + .insert(TransformBundle::from_transform(Transform::from_translation( + structure.chunk_relative_position(coords), + ))); structure.set_chunk_entity(coords, entity); diff --git a/cosmos_server/src/structure/ship/persistence.rs b/cosmos_server/src/structure/ship/persistence.rs index 037d3d7f0..e57c21d9a 100644 --- a/cosmos_server/src/structure/ship/persistence.rs +++ b/cosmos_server/src/structure/ship/persistence.rs @@ -98,8 +98,6 @@ fn even_more_delayed_structure_event( pub(super) fn register(app: &mut App) { app.add_systems(PreUpdate, even_more_delayed_structure_event) - // After to ensure 1 frame delay - // Used to have `.after(even_more_delayed_structure_event)` .add_systems(Update, delayed_structure_event) .add_event::() .add_event::() diff --git a/cosmos_server/src/universe/asteroid_spawner.rs b/cosmos_server/src/universe/asteroid_spawner.rs index d6153bd75..4cb1a4e3d 100644 --- a/cosmos_server/src/universe/asteroid_spawner.rs +++ b/cosmos_server/src/universe/asteroid_spawner.rs @@ -1,7 +1,10 @@ //! Responsible for spawning planets near stars, but for now just spawns a planet at 0, 0, 0. +use std::time::Duration; + use bevy::{ prelude::{in_state, App, Commands, Deref, DerefMut, IntoSystemConfigs, Query, Res, ResMut, Resource, Update, Vec3, With}, + time::common_conditions::on_timer, utils::HashSet, }; use cosmos_core::{ @@ -17,7 +20,7 @@ use cosmos_core::{ use rand::Rng; use crate::{ - init::init_world::ServerSeed, persistence::is_sector_loaded, rng::get_rng_for_sector, state::GameState, + init::init_world::ServerSeed, persistence::is_sector_generated, rng::get_rng_for_sector, state::GameState, structure::asteroid::server_asteroid_builder::ServerAsteroidBuilder, }; @@ -76,19 +79,23 @@ fn spawn_asteroid( for sector in sectors { cache.insert(sector); - if is_sector_loaded(sector) || is_planet_in_sector(§or, &server_seed) { + if sector != Sector::new(25, 25, 25) { + continue; + } + + if is_sector_generated(sector) || is_planet_in_sector(§or, &server_seed) { // This sector has already been loaded, don't regenerate stuff continue; } let mut rng = get_rng_for_sector(&server_seed, §or); - if rng.gen_range(0..100) == 0 { + if rng.gen_range(0..100) < 100 { // Biased towards lower amounts let n_asteroids = (6.0 * (1.0 - (1.0 - rng.gen::()).sqrt())) as usize; - let multiplier = SECTOR_DIMENSIONS - 600.0; - let adder = 300.0 + SECTOR_DIMENSIONS / 2.0; + let multiplier = SECTOR_DIMENSIONS; + let adder = -SECTOR_DIMENSIONS / 2.0; for _ in 0..n_asteroids { let size = rng.gen_range(2..=5); @@ -114,7 +121,17 @@ fn spawn_asteroid( } } +fn print_n(query: Query<&Asteroid>) { + println!("N: {}", query.iter().len()); +} + pub(super) fn register(app: &mut App) { - app.add_systems(Update, spawn_asteroid.run_if(in_state(GameState::Playing))) - .insert_resource(CachedSectors::default()); + app.add_systems( + Update, + spawn_asteroid + .run_if(on_timer(Duration::from_secs(1))) + .run_if(in_state(GameState::Playing)), + ) + .insert_resource(CachedSectors::default()) + .add_systems(Update, print_n); } diff --git a/cosmos_server/src/universe/generation.rs b/cosmos_server/src/universe/generation.rs index ec2282591..81454fb5b 100644 --- a/cosmos_server/src/universe/generation.rs +++ b/cosmos_server/src/universe/generation.rs @@ -2,10 +2,9 @@ use std::f32::consts::{E, TAU}; -use bevy::prelude::{in_state, App, Commands, IntoSystemConfigs, Query, Res, Update, Vec3, With}; +use bevy::prelude::{in_state, App, Commands, IntoSystemConfigs, Name, Query, Res, Update, Vec3, With}; use bevy_rapier3d::prelude::Velocity; use cosmos_core::{ - ecs::bundles::CosmosPbrBundle, entities::player::Player, persistence::LoadingDistance, physics::location::{Location, Sector, SystemUnit, UniverseSystem, SYSTEM_SECTORS}, @@ -111,17 +110,15 @@ fn load_stars_near_players( commands.spawn(( star, - CosmosPbrBundle { - location: Location::new( - Vec3::ZERO, - Sector::new( - ((system.x() as f32 + STAR_POS_OFFSET) * SYSTEM_SECTORS as f32) as SystemUnit, - ((system.y() as f32 + STAR_POS_OFFSET) * SYSTEM_SECTORS as f32) as SystemUnit, - ((system.z() as f32 + STAR_POS_OFFSET) * SYSTEM_SECTORS as f32) as SystemUnit, - ), + Location::new( + Vec3::ZERO, + Sector::new( + ((system.x() as f32 + STAR_POS_OFFSET) * SYSTEM_SECTORS as f32) as SystemUnit, + ((system.y() as f32 + STAR_POS_OFFSET) * SYSTEM_SECTORS as f32) as SystemUnit, + ((system.z() as f32 + STAR_POS_OFFSET) * SYSTEM_SECTORS as f32) as SystemUnit, ), - ..Default::default() - }, + ), + Name::new("Star"), Velocity::zero(), LoadingDistance::new(SYSTEM_SECTORS / 2 + 1, SYSTEM_SECTORS / 2 + 1), )); diff --git a/cosmos_server/src/universe/planet_spawner.rs b/cosmos_server/src/universe/planet_spawner.rs index fadbcac0d..eb245d25b 100644 --- a/cosmos_server/src/universe/planet_spawner.rs +++ b/cosmos_server/src/universe/planet_spawner.rs @@ -26,7 +26,7 @@ use futures_lite::future; use rand::Rng; use crate::{ - init::init_world::ServerSeed, persistence::is_sector_loaded, rng::get_rng_for_sector, state::GameState, + init::init_world::ServerSeed, persistence::is_sector_generated, rng::get_rng_for_sector, state::GameState, structure::planet::server_planet_builder::ServerPlanetBuilder, }; @@ -124,7 +124,7 @@ fn spawn_planet( for sector in to_check_sectors { cache.insert(sector); - if is_sector_loaded(sector) { + if is_sector_generated(sector) { // This sector has already been loaded, don't regenerate stuff continue; }