Skip to content

Commit

Permalink
Merge pull request #205 from AnthonyTornetta/201-save-file-entities-a…
Browse files Browse the repository at this point in the history
…re-created-but-never-actually-loaded

Fixed asteroids being duplicate loaded + generated in wrong sectors
  • Loading branch information
AnthonyTornetta authored Oct 31, 2023
2 parents 433d0d1 + f88ea7e commit 6843f24
Show file tree
Hide file tree
Showing 15 changed files with 229 additions and 77 deletions.
1 change: 1 addition & 0 deletions cosmos_client/src/inventory/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
1 change: 1 addition & 0 deletions cosmos_client/src/netty/gameplay/receiver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
25 changes: 14 additions & 11 deletions cosmos_client/src/ui/crosshair.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,22 @@ use crate::state::game_state::GameState;

fn add_crosshair(mut commands: Commands, asset_server: Res<AssetServer>) {
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 {
Expand Down
1 change: 1 addition & 0 deletions cosmos_client/src/ui/item_renderer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
87 changes: 55 additions & 32 deletions cosmos_core/src/structure/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<ChunkSetEvent>,
) {
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<ChunkInitEvent>,
mut block_reader: EventReader<BlockChangedEvent>,
Expand All @@ -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,
);
}
}

Expand Down
1 change: 1 addition & 0 deletions cosmos_server/src/events/netty/netty_events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
2 changes: 1 addition & 1 deletion cosmos_server/src/persistence/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

Expand Down
4 changes: 2 additions & 2 deletions cosmos_server/src/persistence/player_loading.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand Down Expand Up @@ -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")));
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions cosmos_server/src/structure/asteroid/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
103 changes: 103 additions & 0 deletions cosmos_server/src/structure/asteroid/persistence.rs
Original file line number Diff line number Diff line change
@@ -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<NeedsSaved>, With<Asteroid>)>) {
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<NeedsLoaded>>,
mut event_writer: EventWriter<DelayedStructureLoadEvent>,
mut commands: Commands,
) {
for (entity, s_data) in query.iter() {
if s_data.deserialize_data::<bool>("cosmos:is_asteroid").unwrap_or(false) {
if let Some(mut structure) = s_data.deserialize_data::<Structure>("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<DelayedStructureLoadEvent>,
mut event_writer: EventWriter<EvenMoreDelayedStructureLoadEvent>,
) {
for ev in event_reader.iter() {
event_writer.send(EvenMoreDelayedStructureLoadEvent(ev.0));
}
}

fn even_more_delayed_structure_event(
mut event_reader: EventReader<EvenMoreDelayedStructureLoadEvent>,
mut chunk_set_event_writer: EventWriter<ChunkInitEvent>,
mut structure_loaded_event_writer: EventWriter<StructureLoadedEvent>,
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::<DelayedStructureLoadEvent>()
.add_event::<EvenMoreDelayedStructureLoadEvent>()
.add_systems(First, on_save_structure.after(begin_saving).before(done_saving))
.add_systems(Update, on_load_structure.after(begin_loading).before(done_loading));
}
21 changes: 13 additions & 8 deletions cosmos_server/src/structure/planet/persistence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ fn populate_chunks(
.insert((
serialized_data,
NeedsLoaded,
Name::new("Needs Loaded Chunk"),
NoSendEntity,
ChunkEntity {
structure_entity: needs.structure_entity,
Expand All @@ -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::<ChunkNeedsPopulated>();
}
}
Expand All @@ -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);

Expand Down
2 changes: 0 additions & 2 deletions cosmos_server/src/structure/ship/persistence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<DelayedStructureLoadEvent>()
.add_event::<EvenMoreDelayedStructureLoadEvent>()
Expand Down
Loading

0 comments on commit 6843f24

Please sign in to comment.