Skip to content

Commit

Permalink
Merge pull request #12 from PauMAVA/items
Browse files Browse the repository at this point in the history
ItemStack refactor

Work on this is incomplete and will be followed up by PRs in Feather once `libcraft` is transferred to the new monorepo.
  • Loading branch information
caelunshun authored Mar 3, 2021
2 parents 1a0acb1 + ed86f76 commit 3772479
Show file tree
Hide file tree
Showing 10 changed files with 456 additions and 16 deletions.
2 changes: 0 additions & 2 deletions crates/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
mod biome;
pub mod block;
mod consts;
mod enchantment;
mod entity;
mod gamemode;
mod gamerules;
Expand All @@ -13,7 +12,6 @@ mod positions;

pub use biome::Biome;
pub use consts::*;
pub use enchantment::{Enchantment, EnchantmentKind};
pub use entity::EntityKind;
pub use gamemode::Gamemode;
pub use gamerules::GameRules;
Expand Down
16 changes: 11 additions & 5 deletions crates/generators/python/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from re import split
from pathlib import Path

from typing import List

LIBCRAFT_ROOT = Path(__file__).parents[3]
PRISMARINEJS_BASE_PATH = Path(__file__).parents[1] / "minecraft-data" / "data" / "pc"
Expand Down Expand Up @@ -141,16 +142,21 @@ def generate_enum_property(
return result


def generate_enum(name: str, variants: list[str]) -> str:
"""Generates an enum definition with the provided variants."""
def generate_enum(name: str, variants: List[str], derives: List[str] = [], prelude: str = "") -> str:
"""Generates an enum definition with the provided variants and extra derives."""
body = ','.join(variants) + ','

return f"""
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
extra_derives = "" if len(derives) == 0 else ',' + ','.join(derives)
output = f"""
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord{extra_derives})]"""
if len(prelude) != 0:
output += f"""
{prelude}"""
output += f"""
pub enum {name} {{
{body}
}}
"""
return output


def camel_case(string: str) -> str:
Expand Down
47 changes: 46 additions & 1 deletion crates/generators/python/item.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,56 @@
else:
durabilities[variant] = f"Some({durability})"

output_data = "#[derive(serde::Serialize, serde::Deserialize)]" + generate_enum("Item", items)
output_data = "use serde::{Serialize, Deserialize};"

output_data += generate_enum("Item", items, derives=["Serialize", "Deserialize"],
prelude="#[serde(try_from = \"String\", into = \"&'static str\")]")
output_data += generate_enum_property("Item", "id", "u32", ids, True)
output_data += generate_enum_property("Item", "name", "&str", names, True, "&'static str")
output_data += generate_enum_property("Item", "display_name", "&str", display_names, False, "&'static str")
output_data += generate_enum_property("Item", "stack_size", "u32", stack_sizes)
output_data += generate_enum_property("Item", "durability", "Option<u32>", durabilities)

output_data += f"""
use std::convert::TryFrom;
impl TryFrom<String> for Item {{
type Error = &'static str;
fn try_from(value: String) -> Result<Self, Self::Error> {{
if let Some(item) = Item::from_name(value.as_str()) {{
Ok(item)
}} else {{
Err("Unknown item name.")
}}
}}
}}
"""

output_data += f"""
use std::convert::Into;
impl Into<&'static str> for Item {{
fn into(self) -> &'static str {{
self.name()
}}
}}
"""

output_data += f"""
use std::str::FromStr;
impl FromStr for Item {{
type Err = &'static str;
fn from_str(s: &str) -> Result<Self, Self::Err> {{
if let Some(item) = Item::from_name(s) {{
Ok(item)
}} else {{
Err("Unknown item name.")
}}
}}
}}
"""

output("crates/items/src/item.rs", output_data)
4 changes: 2 additions & 2 deletions crates/items/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
[package]
name = "libcraft-items"
version = "0.1.0"
authors = ["Kalle Kankaanpää"]
authors = ["Kalle Kankaanpää", "Pau Machetti <[email protected]>"]
edition = "2018"

[dependencies]
serde = { version = "1", features = ["derive"] }
serde = { version = "1", features = ["derive"] }
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use serde::{Deserialize, Serialize};

/// An enchantment attached to an item.
#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Enchantment {
#[serde(rename = "id")]
kind: EnchantmentKind,
Expand Down Expand Up @@ -54,7 +54,7 @@ impl Enchantment {
}

/// Kind of an enchantment.
#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum EnchantmentKind {
AquaAffinity,
Expand Down
50 changes: 50 additions & 0 deletions crates/items/src/inventory_slot.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
use crate::item_stack::ItemStackError;
use crate::ItemStack;
use core::mem;

/// Represents an Inventory slot. May be empty
/// or filled (contains an `ItemStack`).
pub enum InventorySlot {
Filled(ItemStack),
Empty,
}

impl Default for InventorySlot {
fn default() -> Self {
InventorySlot::Empty
}
}

impl InventorySlot {
/// Tries to take all items from the `InventorySlot`.
/// If the `InventorySlot` is filled returns the `ItemStack`.
/// If the `InventorySlot` is empty returns `None`.
pub fn take_all(&mut self) -> Option<ItemStack> {
match mem::take(self) {
Self::Filled(stack) => Some(stack),
Self::Empty => None,
}
}

/// Tries to take (split) the specified amount from the associated
/// `ItemStack` to this `InventorySlot`. If this `InventorySlot` is
/// empty, the specified amount is zero, or the resulting stack is
/// empty will return the `ItemStackError::EmptyStack` error. If the
/// amount to take is bigger than the current amount it will return
/// the `ItemStackError::NotEnoughAmount` error. On success returns
/// the taken part of the `ItemStack` as a new one.
pub fn take(&mut self, amount: u32) -> Result<ItemStack, ItemStackError> {
let split = match mem::take(self) {
Self::Empty => return Err(ItemStackError::EmptyStack),
Self::Filled(mut stack) => stack.split(amount),
};
let (stack, res) = match split {
Ok((original, new)) => (original, Ok(new)),
Err((original, error)) => (Some(original), Err(error)),
};
if let Some(stack) = stack {
*self = Self::Filled(stack)
}
res
}
}
41 changes: 38 additions & 3 deletions crates/items/src/item.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// This file is @generated. Please do not edit.
#[derive(
serde::Serialize, serde::Deserialize, Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord,
)]
use serde::{Deserialize, Serialize};
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
#[serde(try_from = "String", into = "&'static str")]
pub enum Item {
Air,
Stone,
Expand Down Expand Up @@ -7872,3 +7872,38 @@ impl Item {
}
}
}
use std::convert::TryFrom;

impl TryFrom<String> for Item {
type Error = &'static str;

fn try_from(value: String) -> Result<Self, Self::Error> {
if let Some(item) = Item::from_name(value.as_str()) {
Ok(item)
} else {
Err("Unknown item name.")
}
}
}

use std::convert::Into;

impl Into<&'static str> for Item {
fn into(self) -> &'static str {
self.name()
}
}

use std::str::FromStr;

impl FromStr for Item {
type Err = &'static str;

fn from_str(s: &str) -> Result<Self, Self::Err> {
if let Some(item) = Item::from_name(s) {
Ok(item)
} else {
Err("Unknown item name.")
}
}
}
Loading

0 comments on commit 3772479

Please sign in to comment.