aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/commands.rs4
-rw-r--r--src/events.rs28
-rw-r--r--src/lib.rs6
-rw-r--r--src/observers.rs31
-rw-r--r--src/payload/components/mod.rs5
-rw-r--r--src/payload/mod.rs2
-rw-r--r--src/preload/events.rs7
-rw-r--r--src/preload/mod.rs38
-rw-r--r--src/preload/resources.rs6
-rw-r--r--src/preload/systems.rs30
-rw-r--r--src/resources.rs8
-rw-r--r--src/systems.rs13
-rw-r--r--src/utils.rs10
13 files changed, 140 insertions, 48 deletions
diff --git a/src/commands.rs b/src/commands.rs
index 616f326..f203adc 100644
--- a/src/commands.rs
+++ b/src/commands.rs
@@ -89,7 +89,7 @@ impl Command for DirworldLockDoorCommand {
});
world.resource_mut::<DirworldTasks>().insert(
format!("Locking {:?}", self.path.file_name().unwrap()),
- task,
+ Some(task),
);
}
}
@@ -163,7 +163,7 @@ impl Command for DirworldUnlockDoorCommand {
});
world.resource_mut::<DirworldTasks>().insert(
format!("Unlocking {:?}", self.path.file_name().unwrap()),
- task,
+ Some(task),
);
}
}
diff --git a/src/events.rs b/src/events.rs
index 7932a67..042c5e6 100644
--- a/src/events.rs
+++ b/src/events.rs
@@ -2,33 +2,27 @@ use std::path::PathBuf;
use bevy::prelude::*;
-/// Events related to activities in the dirworld.
-#[derive(Event)]
-pub enum DirworldNavigationEvent {
- /// Triggered when a room is left.
- LeftRoom {
- /// Path of room just left.
- path: PathBuf,
- },
- /// Triggered when a room is entered.
- EnteredRoom {
- /// Path of room just entered.
- path: PathBuf,
- },
-}
-
/// Event called when leaving a room
#[derive(Debug, Event, Deref, DerefMut, Clone)]
pub struct DirworldLeaveRoom(pub PathBuf);
/// Event called when entering a room
-#[derive(Debug, Event, Deref, DerefMut, Clone)]
-pub struct DirworldEnterRoom(pub PathBuf);
+#[derive(Debug, Event, Clone)]
+pub struct DirworldEnterRoom {
+ pub exited: PathBuf,
+ pub entered: PathBuf,
+}
/// Event called when changing the world root
#[derive(Debug, Event, Deref, DerefMut, Clone)]
pub struct DirworldChangeRoot(pub PathBuf);
+#[derive(Debug, Event, Clone)]
+pub struct DirworldNavigationComplete {
+ pub from: PathBuf,
+ pub to: PathBuf,
+}
+
/// Event called to spawn a dirworld entities
#[derive(Event, Debug, Deref, DerefMut, Clone, Copy)]
pub struct DirworldSpawn(pub Entity);
diff --git a/src/lib.rs b/src/lib.rs
index 7d0749a..5097f2d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -9,10 +9,10 @@ use bevy::{ecs::system::IntoObserverSystem, prelude::*};
use bevy_mod_scripting::core::{AddScriptApiProvider, AddScriptHost, AddScriptHostHandler, ScriptingPlugin};
use bevy_mod_scripting::lua::LuaScriptHost;
use cache::DirworldCache;
-use events::{DirworldChangeRoot, DirworldEnterRoom, DirworldLeaveRoom, DirworldSpawn};
+use events::{DirworldChangeRoot, DirworldEnterRoom, DirworldLeaveRoom, DirworldNavigationComplete, DirworldSpawn};
use occule::Codec;
use preload::{DirworldPreload, DirworldPreloadPlugin};
-use resources::EntryType;
+use resources::{DirworldLastDir, EntryType};
use resources::{
DirworldCodecs, DirworldCurrentDir, DirworldObservers, DirworldRootDir, DirworldTasks,
};
@@ -87,6 +87,7 @@ impl Plugin for DirworldPlugin {
.init_resource::<DirworldRootDir>()
.init_resource::<DirworldCache>()
.init_resource::<DirworldCurrentDir>()
+ .init_resource::<DirworldLastDir>()
.init_resource::<DirworldTasks>()
.init_resource::<DirworldObservers>()
.init_resource::<DirworldCodecs>()
@@ -94,6 +95,7 @@ impl Plugin for DirworldPlugin {
.add_event::<DirworldLeaveRoom>()
.add_event::<DirworldChangeRoot>()
.add_event::<DirworldWatcherEvent>()
+ .add_event::<DirworldNavigationComplete>()
.add_observer(observers::navigate_to_room)
.add_observer(observers::handle_changes)
.add_observer(observers::change_root)
diff --git a/src/observers.rs b/src/observers.rs
index bd1d1a6..faa4749 100644
--- a/src/observers.rs
+++ b/src/observers.rs
@@ -7,9 +7,17 @@ use notify::{
};
use crate::{
- cache::DirworldCache, components::{DirworldEntity, Persist}, events::{DirworldChangeRoot, DirworldEnterRoom, DirworldLeaveRoom}, preload::{load_entity, PreloadState, RoomAssets}, resources::{
- DirworldCodecs, DirworldCurrentDir, DirworldObservers, DirworldRootDir,
- }, utils::{despawn_entity_by_path, extract_entity_payload}, DirworldWatcherEvent
+ cache::DirworldCache,
+ components::{DirworldEntity, Persist},
+ events::{
+ DirworldChangeRoot, DirworldEnterRoom, DirworldLeaveRoom, DirworldNavigationComplete,
+ },
+ preload::{load_entity, DirworldPreloadBegin, PreloadState, RoomAssets},
+ resources::{
+ DirworldCodecs, DirworldCurrentDir, DirworldObservers, DirworldRootDir, DirworldTasks,
+ },
+ utils::{despawn_entity_by_path, extract_entity_payload},
+ DirworldWatcherEvent,
};
/// On navigation from a room, insert modified payloads into the cache
@@ -35,11 +43,16 @@ pub fn navigate_to_room(
codecs: Res<DirworldCodecs>,
mut commands: Commands,
mut event_writer: EventWriter<DirworldEnterRoom>,
+ mut preload_event_writer: EventWriter<DirworldPreloadBegin>,
mut current_dir: ResMut<DirworldCurrentDir>,
mut next_preload_state: ResMut<NextState<PreloadState>>,
mut room_assets: ResMut<RoomAssets>,
+ mut dirworld_tasks: ResMut<DirworldTasks>,
) {
- let path = &trigger.event().0;
+ let DirworldEnterRoom {
+ exited: old_path,
+ entered: path,
+ } = &trigger.event();
let room_payload = extract_entity_payload(&path.join(".door"), &codecs).0;
*current_dir = DirworldCurrentDir {
@@ -60,6 +73,7 @@ pub fn navigate_to_room(
root_dir
.clone()
.map(|root_dir| {
+ info!("Root: {root_dir:?}, Path: {path:?}");
if root_dir == *path {
None
} else {
@@ -75,6 +89,7 @@ pub fn navigate_to_room(
}
};
+ dirworld_tasks.insert("Loading Room".into(), None);
for entry in entries {
load_entity(
&entry,
@@ -86,6 +101,7 @@ pub fn navigate_to_room(
&mut room_assets,
);
}
+ preload_event_writer.send(DirworldPreloadBegin { old_path: old_path.clone(), path: path.clone() });
event_writer.send(trigger.event().clone());
}
@@ -161,9 +177,12 @@ pub fn change_root(
commands.trigger(DirworldLeaveRoom(old_dir.to_path_buf()));
};
- let new_root = &trigger.event().0;
+ let new_root = &trigger.event().0.canonicalize().unwrap();
info!("Changing Root to {}", new_root.display());
**root_dir = Some(new_root.to_path_buf());
- commands.trigger(DirworldEnterRoom(new_root.to_path_buf()));
+ commands.trigger(DirworldEnterRoom {
+ exited: new_root.to_path_buf(),
+ entered: new_root.to_path_buf(),
+ });
}
diff --git a/src/payload/components/mod.rs b/src/payload/components/mod.rs
index fc24ac1..2812d73 100644
--- a/src/payload/components/mod.rs
+++ b/src/payload/components/mod.rs
@@ -9,6 +9,11 @@ use yarnspinner::core::YarnValue;
#[derive(Serialize, Deserialize, Clone, Default, Deref, DerefMut, Debug)]
pub struct Transform(pub bevy::prelude::Transform);
+/// Transform for the destination of a door
+/// Used to determine where to spawn ".." door and player when entering a room
+#[derive(Serialize, Deserialize, Clone, Default, Deref, DerefMut, Debug)]
+pub struct DoorDestination(pub bevy::prelude::Transform);
+
/// Payload component that represent's an entity's name
#[derive(Serialize, Deserialize, Clone, Default, Deref, DerefMut, Debug)]
pub struct Name(pub String);
diff --git a/src/payload/mod.rs b/src/payload/mod.rs
index 68e23a0..3639997 100644
--- a/src/payload/mod.rs
+++ b/src/payload/mod.rs
@@ -27,6 +27,8 @@ pub struct DirworldEntityPayload {
pub relationships: Option<components::Relationships>,
/// Pickup information for this entity
pub pickup: Option<components::Pickup>,
+ /// Door destination
+ pub door_destination: Option<components::DoorDestination>,
}
impl DirworldEntityPayload {
diff --git a/src/preload/events.rs b/src/preload/events.rs
index 7167d73..a6f9d16 100644
--- a/src/preload/events.rs
+++ b/src/preload/events.rs
@@ -1,3 +1,5 @@
+use std::path::PathBuf;
+
use bevy::prelude::*;
/// Event used to trigger preload callbacks after the asset file has been pre-processed to extract
@@ -10,3 +12,8 @@ pub struct DirworldPreload {
pub data: Option<Vec<u8>>,
}
+#[derive(Debug, Event, Clone)]
+pub struct DirworldPreloadBegin {
+ pub old_path: PathBuf,
+ pub path: PathBuf,
+}
diff --git a/src/preload/mod.rs b/src/preload/mod.rs
index b90db38..266cb37 100644
--- a/src/preload/mod.rs
+++ b/src/preload/mod.rs
@@ -13,8 +13,8 @@ mod systems;
mod resources;
pub use resources::*;
-mod events;
-pub use events::DirworldPreload;
+pub mod events;
+pub use events::*;
pub(crate) struct DirworldPreloadPlugin;
@@ -22,9 +22,17 @@ impl Plugin for DirworldPreloadPlugin {
fn build(&self, app: &mut App) {
app.add_systems(
PostUpdate,
- systems::handle_preload.run_if(in_state(PreloadState::Loading)),
+ (
+ systems::cache_preload_paths,
+ systems::handle_preload.run_if(in_state(PreloadState::Loading)),
+ ),
)
.add_systems(OnEnter(PreloadState::Done), systems::handle_spawn)
+ .add_event::<DirworldPreloadBegin>()
+ .insert_resource(PreloadPaths {
+ src: PathBuf::new(),
+ dst: PathBuf::new(),
+ })
.init_resource::<RoomAssets>()
.init_state::<PreloadState>();
}
@@ -52,6 +60,7 @@ pub fn load_entity(
preload_state: &mut NextState<PreloadState>,
room_assets: &mut RoomAssets,
) {
+ info!("Entity: {entry:?}");
let (mut payload, data) = extract_entity_payload(&entry, &codecs);
payload = payload.map(|p| cache.get_entity_cache(&entry).unwrap_or(p));
let entry_type = if entry.is_dir() {
@@ -59,13 +68,26 @@ pub fn load_entity(
} else {
EntryType::File(entry.extensions())
};
- let transform = payload
- .as_ref()
- .map(|payload| payload.transform.clone())
- .unwrap_or_default();
+ let transform = if entry.file_name().is_none() {
+ payload
+ .as_ref()
+ .map(|payload| {
+ payload
+ .door_destination
+ .as_ref()
+ .expect("Door destination missing from payload!")
+ .0
+ })
+ .unwrap_or_default()
+ } else {
+ payload
+ .as_ref()
+ .map(|payload| payload.transform.0)
+ .unwrap_or_default()
+ };
let entity = commands
.spawn((
- *transform,
+ transform,
Visibility::Inherited,
DirworldEntity {
path: entry.clone(),
diff --git a/src/preload/resources.rs b/src/preload/resources.rs
index 4060c10..9cfec70 100644
--- a/src/preload/resources.rs
+++ b/src/preload/resources.rs
@@ -5,3 +5,9 @@ use bevy::prelude::*;
/// A map of asset handles required by each entry in a room, indexed by their paths
#[derive(Resource, Default, Debug, Deref, DerefMut)]
pub struct RoomAssets(pub HashMap<PathBuf, HashMap<String, UntypedHandle>>);
+
+#[derive(Resource, Clone)]
+pub struct PreloadPaths {
+ pub src: PathBuf,
+ pub dst: PathBuf,
+}
diff --git a/src/preload/systems.rs b/src/preload/systems.rs
index ec867ae..330c897 100644
--- a/src/preload/systems.rs
+++ b/src/preload/systems.rs
@@ -1,13 +1,31 @@
use bevy::prelude::*;
-use crate::{components::DirworldEntity, events::DirworldSpawn, resources::{DirworldObservers, EntryType}, Extensions};
+use crate::{
+ components::DirworldEntity,
+ events::{DirworldNavigationComplete, DirworldSpawn},
+ resources::{DirworldObservers, DirworldTasks, EntryType},
+ Extensions,
+};
-use super::{PreloadState, RoomAssets};
+use super::{
+ DirworldPreloadBegin, PreloadPaths, PreloadState, RoomAssets,
+};
+
+pub fn cache_preload_paths(
+ mut event_reader: EventReader<DirworldPreloadBegin>,
+ mut paths: ResMut<PreloadPaths>,
+) {
+ for DirworldPreloadBegin { old_path, path } in event_reader.read() {
+ paths.src = old_path.canonicalize().unwrap();
+ paths.dst = path.canonicalize().unwrap();
+ }
+}
pub fn handle_preload(
asset_server: Res<AssetServer>,
room_assets: Res<RoomAssets>,
mut next_state: ResMut<NextState<PreloadState>>,
+ mut dirworld_tasks: ResMut<DirworldTasks>,
) {
if room_assets.is_empty()
|| room_assets
@@ -17,13 +35,16 @@ pub fn handle_preload(
{
info!("Preload Done.");
next_state.set(PreloadState::Done);
+ dirworld_tasks.remove("Loading Room");
}
}
pub fn handle_spawn(
+ preload_paths: Res<PreloadPaths>,
dirworld_entity_query: Query<(Entity, &DirworldEntity)>,
mut commands: Commands,
observers: Res<DirworldObservers>,
+ mut event_writer: EventWriter<DirworldNavigationComplete>,
) {
info!("Spawning");
for (entity, DirworldEntity { path, .. }) in dirworld_entity_query.iter() {
@@ -37,5 +58,8 @@ pub fn handle_spawn(
commands.trigger_targets(DirworldSpawn(entity), observer.clone());
}
}
+ event_writer.send(DirworldNavigationComplete {
+ from: preload_paths.src.clone(),
+ to: preload_paths.dst.clone(),
+ });
}
-
diff --git a/src/resources.rs b/src/resources.rs
index bf0c072..f916deb 100644
--- a/src/resources.rs
+++ b/src/resources.rs
@@ -12,16 +12,19 @@ pub struct DirworldRootDir(pub Option<PathBuf>);
/// Current directory of the world
#[derive(Resource, Default)]
-pub struct DirworldCurrentDir{
+pub struct DirworldCurrentDir {
/// Path of current directory
pub path: PathBuf,
/// Payload (contents of .door file) in current directory, if present
pub payload: Option<DirworldEntityPayload>,
}
+#[derive(Resource, Deref, DerefMut, Default, Debug)]
+pub struct DirworldLastDir(pub PathBuf);
+
/// Running background tasks
#[derive(Default, Resource, Deref, DerefMut)]
-pub struct DirworldTasks(pub BTreeMap<String, Task<Option<CommandQueue>>>);
+pub struct DirworldTasks(pub BTreeMap<String, Option<Task<Option<CommandQueue>>>>);
/// A map between file types and their corresponding preload/spawn callback observers
#[derive(Debug, Default, Resource, Deref, DerefMut)]
@@ -39,4 +42,3 @@ pub enum EntryType {
/// A folder
Folder,
}
-
diff --git a/src/systems.rs b/src/systems.rs
index d6840ee..b95b14f 100644
--- a/src/systems.rs
+++ b/src/systems.rs
@@ -6,13 +6,16 @@ use bevy::{
use crate::resources::DirworldTasks;
pub fn remove_completed_tasks(mut commands: Commands, mut tasks: ResMut<DirworldTasks>) {
- tasks.retain(|_, task| {
- if task.is_finished() {
- if let Some(Some(mut command_queue)) = block_on(future::poll_once(&mut *task)) {
- commands.append(&mut command_queue);
+ tasks.retain(|_, task| match task {
+ Some(task) => {
+ if task.is_finished() {
+ if let Some(Some(mut command_queue)) = block_on(future::poll_once(&mut *task)) {
+ commands.append(&mut command_queue);
+ }
}
+ !task.is_finished()
}
- !task.is_finished()
+ None => true,
});
}
diff --git a/src/utils.rs b/src/utils.rs
index 74451ae..a8ee2b8 100644
--- a/src/utils.rs
+++ b/src/utils.rs
@@ -3,7 +3,8 @@ use std::{fs, path::PathBuf};
use bevy::prelude::*;
use crate::{
- components::DirworldEntity, payload::DirworldEntityPayload, resources::DirworldCodecs, Extensions
+ components::DirworldEntity, payload::DirworldEntityPayload, resources::DirworldCodecs,
+ Extensions,
};
/// Extracts the binary payload from a file
@@ -15,7 +16,12 @@ pub fn extract_entity_payload(
let mut payload = None;
if path.is_dir() {
- let payload_file_path = path.join(".door");
+ let payload_file_path = if path.file_name().is_none() {
+ path.parent().expect(".. missing parent somehow").join(".door")
+ } else {
+ path.join(".door")
+ };
+ info!("{payload_file_path:?}");
if payload_file_path.exists() {
if let Ok(payload_file_data) = fs::read(&payload_file_path) {
match rmp_serde::from_slice::<DirworldEntityPayload>(&payload_file_data) {