-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
378 additions
and
20 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
[package] | ||
name = "rimecraft-item" | ||
version = "0.1.0" | ||
edition = "2021" | ||
authors = ["JieningYu <[email protected]>"] | ||
description = "Minecraft Item primitives and registry" | ||
repository = "https://github.com/rimecraft-rs/rimecraft/" | ||
license = "AGPL-3.0-or-later" | ||
categories = [] | ||
|
||
[badges] | ||
maintenance = { status = "passively-maintained" } | ||
|
||
[dependencies] | ||
rimecraft-registry = { path = "../../util/registry" } | ||
rimecraft-fmt = { path = "../../util/fmt" } | ||
rimecraft-freezer = { path = "../../util/freezer" } | ||
rimecraft-attachment = { path = "../../util/attachment" } | ||
rimecraft-serde-update = { path = "../../util/serde-update", optional = true } | ||
fastnbt = "2.4" | ||
rimecraft-nbt-ext = { path = "../../util/nbt-ext" } | ||
serde = { version = "1.0", optional = true, features = ["derive"] } | ||
|
||
[features] | ||
default = ["serde"] | ||
serde = [ | ||
"dep:serde", | ||
"rimecraft-registry/serde", | ||
"rimecraft-attachment/serde", | ||
"dep:rimecraft-serde-update", | ||
] | ||
|
||
[lints] | ||
workspace = true |
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,115 @@ | ||
//! Minecraft Item primitives and registry. | ||
|
||
use std::{marker::PhantomData, num::NonZeroU32}; | ||
|
||
use rimecraft_fmt::Formatting; | ||
use rimecraft_registry::{ProvideRegistry, Reg}; | ||
|
||
mod stack; | ||
|
||
pub use stack::ItemStack; | ||
|
||
/// Item containing settings. | ||
#[derive(Debug)] | ||
pub struct RawItem<P> { | ||
settings: Settings, | ||
_marker: PhantomData<P>, | ||
} | ||
|
||
impl<P> RawItem<P> { | ||
/// Creates a new `Item` with the given settings. | ||
#[inline] | ||
pub const fn new(settings: Settings) -> Self { | ||
Self { | ||
settings, | ||
_marker: PhantomData, | ||
} | ||
} | ||
|
||
/// Returns the settings of the item. | ||
#[inline] | ||
pub fn settings(&self) -> &Settings { | ||
&self.settings | ||
} | ||
} | ||
|
||
impl<P> From<Settings> for RawItem<P> { | ||
#[inline] | ||
fn from(settings: Settings) -> Self { | ||
Self::new(settings) | ||
} | ||
} | ||
|
||
impl<'r, K, P> ProvideRegistry<'r, K, Self> for RawItem<P> | ||
where | ||
P: ProvideRegistry<'r, K, Self>, | ||
{ | ||
#[inline] | ||
fn registry() -> &'r rimecraft_registry::Registry<K, Self> { | ||
P::registry() | ||
} | ||
} | ||
|
||
/// An item usable by players and other entities. | ||
pub type Item<'r, K, P> = Reg<'r, K, RawItem<P>>; | ||
|
||
/// A trait for converting a value to an [`Item`]. | ||
pub trait ToItem<'s, 'r, K, P> { | ||
/// Converts the value to an [`Item`]. | ||
fn to_item(&'s self) -> Item<'r, K, P>; | ||
} | ||
|
||
/// The max item count of an `ItemStack`. | ||
pub const MAX_STACK_COUNT: u32 = 64; | ||
|
||
/// Settings of an [`Item`]. | ||
/// | ||
/// A setting configure behaviors common to all items, such as the | ||
/// stack's max count. | ||
#[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||
pub struct Settings { | ||
/// The maximum count of the item that can be stacked in a single slot. | ||
pub max_count: NonZeroU32, | ||
/// The maximum amount of damage the item can take. | ||
pub max_damage: Option<NonZeroU32>, | ||
|
||
/// The rarity of the item. | ||
pub rarity: Rarity, | ||
} | ||
|
||
impl Default for Settings { | ||
#[inline] | ||
fn default() -> Self { | ||
Self { | ||
max_count: NonZeroU32::new(MAX_STACK_COUNT).unwrap(), | ||
max_damage: None, | ||
rarity: Default::default(), | ||
} | ||
} | ||
} | ||
|
||
/// Rarity of an item. | ||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Default)] | ||
pub enum Rarity { | ||
/// Common rarity. | ||
#[default] | ||
Common, | ||
/// Uncommon rarity. | ||
Uncommon, | ||
/// Rare rarity. | ||
Rare, | ||
/// Epic rarity. | ||
Epic, | ||
} | ||
|
||
impl From<Rarity> for Formatting { | ||
#[inline] | ||
fn from(value: Rarity) -> Self { | ||
match value { | ||
Rarity::Common => Formatting::White, | ||
Rarity::Uncommon => Formatting::Yellow, | ||
Rarity::Rare => Self::Aqua, | ||
Rarity::Epic => Self::LightPurple, | ||
} | ||
} | ||
} |
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,169 @@ | ||
use rimecraft_attachment::Attachments; | ||
use rimecraft_nbt_ext::Compound; | ||
|
||
use std::{hash::Hash, marker::PhantomData}; | ||
|
||
use crate::{Item, ToItem}; | ||
|
||
/// A stack of items. | ||
/// | ||
/// This is a data container that holds the item count and the stack's NBT. | ||
#[derive(Debug)] | ||
#[cfg_attr( | ||
feature = "serde", | ||
derive(serde::Serialize, serde::Deserialize), | ||
serde(bound( | ||
serialize = "K: serde::Serialize + Hash + Eq", | ||
deserialize = r#" | ||
'r: 'de, | ||
K: serde::Deserialize<'de> + rimecraft_serde_update::Update<'de> + Hash + Eq + std::fmt::Debug + 'r, | ||
P: InitAttachments<K> + rimecraft_registry::ProvideRegistry<'r, K, crate::RawItem<P>> + 'r"# | ||
)) | ||
)] | ||
pub struct ItemStack<'r, K, P> { | ||
#[cfg_attr(feature = "serde", serde(rename = "id"))] | ||
item: Item<'r, K, P>, | ||
|
||
#[cfg_attr(feature = "serde", serde(rename = "Count"))] | ||
count: u32, | ||
|
||
/// Item stack's custom NBT. | ||
#[cfg_attr(feature = "serde", serde(rename = "tag"), serde(default))] | ||
nbt: Option<Compound>, | ||
|
||
#[cfg_attr( | ||
feature = "serde", | ||
serde(skip_serializing_if = "should_skip_attachment_ser"), | ||
serde(default), | ||
serde(serialize_with = "ser_attachments"), | ||
serde(deserialize_with = "deser_attachments") | ||
)] | ||
attachments: (Attachments<K>, PhantomData<P>), | ||
} | ||
|
||
#[cfg(feature = "serde")] | ||
fn should_skip_attachment_ser<K, P>(attachments: &(Attachments<K>, PhantomData<P>)) -> bool { | ||
attachments.0.is_persistent_data_empty() | ||
} | ||
|
||
#[cfg(feature = "serde")] | ||
fn ser_attachments<K, P, S>( | ||
attachments: &(Attachments<K>, PhantomData<P>), | ||
serializer: S, | ||
) -> Result<S::Ok, S::Error> | ||
where | ||
S: serde::Serializer, | ||
K: serde::Serialize + Hash + Eq, | ||
{ | ||
serde::Serialize::serialize(&attachments.0, serializer) | ||
} | ||
|
||
#[cfg(feature = "serde")] | ||
fn deser_attachments<'de, K, P, D>( | ||
deserializer: D, | ||
) -> Result<(Attachments<K>, PhantomData<P>), <D as serde::Deserializer<'de>>::Error> | ||
where | ||
D: serde::Deserializer<'de>, | ||
P: InitAttachments<K>, | ||
K: serde::Deserialize<'de> + rimecraft_serde_update::Update<'de> + Hash + Eq, | ||
{ | ||
use rimecraft_serde_update::Update; | ||
let mut attachments = Attachments::new(); | ||
P::init_attachments(&mut attachments); | ||
attachments.update(deserializer)?; | ||
Ok((attachments, PhantomData)) | ||
} | ||
|
||
impl<'r, K, P> ItemStack<'r, K, P> | ||
where | ||
P: InitAttachments<K>, | ||
{ | ||
/// Creates a new item stack with the given item and count. | ||
#[inline] | ||
pub fn new(item: Item<'r, K, P>, count: u32) -> Self { | ||
Self::with_nbt(item, count, None) | ||
} | ||
|
||
/// Creates a new item stack with the given item, count, | ||
/// and custom NBT tag. | ||
pub fn with_nbt(item: Item<'r, K, P>, count: u32, nbt: Option<Compound>) -> Self { | ||
let mut attachments = Attachments::new(); | ||
P::init_attachments(&mut attachments); | ||
|
||
Self { | ||
item, | ||
count, | ||
nbt, | ||
attachments: (attachments, PhantomData), | ||
} | ||
} | ||
} | ||
|
||
impl<'r, K, P> ItemStack<'r, K, P> { | ||
/// Returns the item of the stack. | ||
#[inline] | ||
pub fn item(&self) -> Item<'r, K, P> { | ||
self.item | ||
} | ||
|
||
/// Returns the count of the stack. | ||
#[inline] | ||
pub fn count(&self) -> u32 { | ||
self.count | ||
} | ||
|
||
/// Returns the custom NBT of the stack. | ||
#[inline] | ||
pub fn nbt(&self) -> Option<&Compound> { | ||
self.nbt.as_ref() | ||
} | ||
|
||
/// Returns a mutable reference to the custom NBT of the stack. | ||
#[inline] | ||
pub fn nbt_mut(&mut self) -> Option<&mut Compound> { | ||
self.nbt.as_mut() | ||
} | ||
|
||
/// Returns the custom NBT of the stack, create one if it does not exist. | ||
#[inline] | ||
pub fn get_or_create_nbt(&mut self) -> &mut Compound { | ||
self.nbt.get_or_insert_with(Compound::new) | ||
} | ||
|
||
/// Sets the count of the stack. | ||
#[inline] | ||
pub fn set_count(&mut self, count: u32) { | ||
self.count = count; | ||
} | ||
|
||
/// Sets the custom NBT of the stack. | ||
#[inline] | ||
pub fn set_nbt(&mut self, nbt: Option<Compound>) { | ||
self.nbt = nbt; | ||
} | ||
|
||
/// Returns the attachments of the stack. | ||
#[inline] | ||
pub fn attachments(&self) -> &Attachments<K> { | ||
&self.attachments.0 | ||
} | ||
|
||
/// Returns the mutable view of attachments of the stack. | ||
#[inline] | ||
pub fn attachments_mut(&mut self) -> &mut Attachments<K> { | ||
&mut self.attachments.0 | ||
} | ||
} | ||
|
||
impl<'s, 'r, K, P> ToItem<'s, 'r, K, P> for ItemStack<'r, K, P> { | ||
#[inline] | ||
fn to_item(&'s self) -> Item<'r, K, P> { | ||
self.item | ||
} | ||
} | ||
|
||
/// A trait for initializing attachments of an item stack. | ||
pub trait InitAttachments<K> { | ||
/// Initializes the attachments of the item stack. | ||
fn init_attachments(attachments: &mut Attachments<K>); | ||
} |
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
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
Oops, something went wrong.