ryot 0.2.2

MMORPG library based on the concepts of open tibia written in rust and bevy.
Documentation
use self::elevation::{apply_elevation, Elevation};
use crate::prelude::*;
use bevy::prelude::*;
use core::fmt;
use serde::{Deserialize, Serialize};
use std::marker::PhantomData;

pub mod elevation;
pub mod tile_flags;

pub struct GamePlugin<C: AppearanceAssets>(PhantomData<C>);

impl<C: AppearanceAssets> GamePlugin<C> {
    pub fn new() -> Self {
        Self(PhantomData)
    }
}

impl<C: AppearanceAssets> Default for GamePlugin<C> {
    fn default() -> Self {
        Self::new()
    }
}

impl<C: AppearanceAssets> Plugin for GamePlugin<C> {
    fn build(&self, app: &mut App) {
        app.add_event::<LoadObjects>()
            .add_systems(Update, apply_elevation::<C>);
    }
}

#[derive(
    Component,
    Clone,
    Copy,
    Debug,
    Serialize,
    Deserialize,
    PartialEq,
    Eq,
    Hash,
    Default,
    Reflect,
    PartialOrd,
    Ord,
)]
pub enum GameObjectId {
    #[default]
    None,
    Object(u32),
    Outfit(u32),
    Effect(u32),
    Missile(u32),
}

impl GameObjectId {
    pub fn is_none(&self) -> bool {
        matches!(self, Self::None)
    }

    pub fn as_group_and_id(&self) -> Option<(AppearanceGroup, u32)> {
        match self {
            GameObjectId::None => None,
            GameObjectId::Object(id) => Some((AppearanceGroup::Object, *id)),
            GameObjectId::Outfit(id) => Some((AppearanceGroup::Outfit, *id)),
            GameObjectId::Effect(id) => Some((AppearanceGroup::Effect, *id)),
            GameObjectId::Missile(id) => Some((AppearanceGroup::Missile, *id)),
        }
    }

    pub fn group(&self) -> Option<AppearanceGroup> {
        self.as_group_and_id().map(|(group, _)| group)
    }

    pub fn id(&self) -> Option<u32> {
        self.as_group_and_id().map(|(_, id)| id)
    }
}

impl fmt::Display for GameObjectId {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            GameObjectId::None => write!(f, "None"),
            GameObjectId::Object(id) => write!(f, "Object({})", id),
            GameObjectId::Outfit(id) => write!(f, "Outfit({})", id),
            GameObjectId::Effect(id) => write!(f, "Effect({})", id),
            GameObjectId::Missile(id) => write!(f, "Missile({})", id),
        }
    }
}

#[derive(Bundle, Copy, Clone, Debug)]
pub struct GameObjectBundle {
    pub object_id: GameObjectId,
    pub position: TilePosition,
    pub elevation: Elevation,
    pub layer: Layer,
}

impl GameObjectBundle {
    pub fn new(object_id: GameObjectId, position: TilePosition, layer: Layer) -> Self {
        Self {
            object_id,
            position,
            layer,
            elevation: default(),
        }
    }
}

#[derive(Event, Clone, Debug, Deref, DerefMut)]
pub struct LoadObjects(pub Vec<GameObjectBundle>);