forked from fishfolk/jumpy
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(kick_bomb): Add spawn kickbomb command to allow spawning from gam…
…eplay code without interfering with map hydration (fishfolk#968) `commands.add(KickBombCommand::spawn_kick_bomb(Some(entity), transform, kick_bomb_meta_handle)` may be used to spawn a kick bomb. - If entity is passed in it will initialize kick bomb components on this entity (mostly to support hydration from map elements), otherwise None will make it create an entity for you. - The handle is untyped handle (can use `handle.untyped()` to convert to this), it supports `Handle<ElementMeta>` or `Handle<KickBombMeta>` automatically. This command adds a `KickBombHandle` containing `Handle<KickBombMeta>`, this should be used to get meta for entities. The kick bomb systems now use this instead of `Handle<ElementMeta>`. Gameplay systems were also updated such that usages of components `MapElementHydrated` and `DehydratedOutOfBounds` (things specific to map spawned kickbombs) are optionally used, meaning these systems still run for gameplay spawned kickbombs missing these components. Under the hood, `try_cast_meta_handle` helper function was added to help convert an untyped `Handle<KickBombMeta>` or `Handle<ElementMeta>` to `Handle<KickBombMeta>`. This function is generic and may be used for other gameplay items that we refactor to add spawn commands to separate item spawn logic from map spawning. I tested this and the map spawned kickbombs will still respawn after use, but the gameplay spawned ones do not.
- Loading branch information
1 parent
8f3cd11
commit 609b11c
Showing
3 changed files
with
190 additions
and
92 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,3 +8,5 @@ mod rect; | |
pub use rect::*; | ||
mod macros; | ||
pub use macros::*; | ||
mod metadata; | ||
pub use metadata::*; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
//! Utilities for asset and meta data handling. | ||
|
||
use crate::prelude::*; | ||
|
||
/// Error type for failure to resolve [`UntypedHandle`] to metadata asset from `Handle<T>` or `Handle<ElementMeta>` | ||
/// (where `T` is metadata type). | ||
#[derive(thiserror::Error, Debug, Clone)] | ||
pub enum MetaHandleCastError { | ||
#[error("UntypedHandle does not represent Handle<{0}> or Handle<ElementMeta>")] | ||
BadHandleType(String), | ||
#[error("UntypedHandle maps to Handle<ElementMeta> but ElementMeta inner handle does not cast to {0}")] | ||
ElementDataMismatch(String), | ||
#[error("Failed to retrieve asset for handle (required for cast type valdiation)")] | ||
InvalidHandle, | ||
} | ||
|
||
/// Try to get metadata handle from [`UntypedHandle`] that may represent direct handle to meta (`Handle<T>`) | ||
/// or `Handle<ElementMeta>` where [`ElementMeta`]'s data is castable to `Handle<T>`. | ||
/// | ||
/// [`Handle::untyped`] can be used to convert to [`UntypedHandle`]. | ||
/// | ||
/// This is useful for code that wants to spawn an item and take UntypedHandle to allow either direct meta handle | ||
/// or `Handle<ElementMeta>` as argument. | ||
pub fn try_cast_meta_handle<T: HasSchema>( | ||
handle: UntypedHandle, | ||
assets: &AssetServer, | ||
) -> Result<Handle<T>, MetaHandleCastError> { | ||
// Get untyped asset from handle or error on failure | ||
let asset = assets | ||
.try_get_untyped(handle) | ||
.ok_or(MetaHandleCastError::InvalidHandle)?; | ||
|
||
// If asset casts to T, return it as Handle<T> | ||
if asset.try_cast_ref::<T>().is_ok() { | ||
return Ok(handle.typed::<T>()); | ||
} | ||
|
||
// Check if handle type is ElementMeta | ||
if let Ok(element_meta) = asset.try_cast_ref::<ElementMeta>() { | ||
// Does element data cast to T? | ||
if assets.get(element_meta.data).try_cast_ref::<T>().is_ok() { | ||
// Return ElementMeta's data as Handle<T> | ||
Ok(element_meta.data.untyped().typed()) | ||
} else { | ||
// ElementMeta data does not cast to T. | ||
Err(MetaHandleCastError::ElementDataMismatch( | ||
std::any::type_name::<T>().to_string(), | ||
)) | ||
} | ||
} else { | ||
// UntypedHandle is neither Handle<T> or Handle<ElementMeta>. | ||
Err(MetaHandleCastError::BadHandleType( | ||
std::any::type_name::<T>().to_string(), | ||
)) | ||
} | ||
} |