Skip to content

Commit

Permalink
Merge pull request #38 from Bryntet/master
Browse files Browse the repository at this point in the history
Add Player Inventory
  • Loading branch information
Snowiiii authored Aug 20, 2024
2 parents 3b55bc4 + 006eacf commit 5445975
Show file tree
Hide file tree
Showing 11 changed files with 227 additions and 31 deletions.
88 changes: 83 additions & 5 deletions pumpkin-inventory/src/player.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,27 @@ use pumpkin_world::item::Item;
#[allow(dead_code)]
pub struct PlayerInventory {
// Main Inventory + Hotbar
crafting: [Option<Item>; 4],
crafting_output: Option<Item>,
items: [Option<Item>; 36],
armor: [Option<Item>; 4],
offhand: Option<Item>,
// current selected slot in hortbar
selected: i16,
// current selected slot in hotbar
selected: usize,
}

pub struct Hotbar<'a>(&'a mut [Option<Item>;9]);

impl Hotbar<'_> {
fn get_mut(&mut self, index: usize) -> &mut Option<Item> {
&mut self.0[index]
}
}

pub struct Armor<'a>(&'a mut [Option<Item>; 4]);



impl Default for PlayerInventory {
fn default() -> Self {
Self::new()
Expand All @@ -19,18 +33,82 @@ impl Default for PlayerInventory {
impl PlayerInventory {
pub fn new() -> Self {
Self {
crafting: [None; 4],
crafting_output: None,
items: [None; 36],
armor: [None; 4],
offhand: None,
// TODO: What when player spawns in with an different index ?
selected: 0,
}
}

/// Set the contents of an item in a slot
///
/// ## Slot
/// The slot according to https://wiki.vg/Inventory#Player_Inventory
///
/// ## Item
/// The optional item to place in the slot
///
/// ## Item allowed override
/// An override, which when enabled, makes it so that invalid items, can be placed in slots they normally can't.
/// Useful functionality for plugins in the future.
pub fn set_slot(&mut self, slot: usize, item: Option<Item>, item_allowed_override: bool) {
match slot {
0 => {
// TODO: Add crafting check here
self.crafting_output = item
}
1..=4 => {
self.crafting[slot-1] = item
}
5..=8 => {
match item {
None => {
self.armor[slot-4] = None
},
Some(item) => {
// TODO: Replace asserts with error handling
match slot-5 {
0 => {
assert!(item.is_helmet() || item_allowed_override);
self.armor[0] = Some(item);
}
1 => {
assert!(item.is_chestplate() || item_allowed_override);
self.armor[1] = Some(item)
}
2 => {
assert!(item.is_leggings() || item_allowed_override);
self.armor[2] = Some(item);
}
3 => {
assert!(item.is_boots() || item_allowed_override);
self.armor[3] = Some(item)
}
_ => unreachable!()
}
}
}
}
9..=44 => {
self.items[slot-9] = item;
}
45 => {
self.offhand = item;
}
_ => unreachable!()
}
}

pub fn set_slot(_slot: u32, _item: Item) {}

pub fn set_selected(&mut self, slot: i16) {
pub fn set_selected(&mut self, slot: usize) {
assert!((0..9).contains(&slot));
self.selected = slot;
}

pub fn held_item(&self) -> Option<&Item> {
debug_assert!((0..9).contains(&self.selected));
self.items[self.selected+36-9].as_ref()
}
}
4 changes: 2 additions & 2 deletions pumpkin-protocol/src/server/play/s_set_creative_slot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ use crate::slot::Slot;
#[allow(dead_code)]
#[packet(0x32)]
pub struct SSetCreativeSlot {
slot: i16,
clicked_item: Slot,
pub slot: i16,
pub clicked_item: Slot,
}
22 changes: 21 additions & 1 deletion pumpkin-protocol/src/slot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use serde::{
de::{self, SeqAccess, Visitor},
Deserialize,
};

use pumpkin_world::item::Item;
use crate::VarInt;

#[derive(Debug, Clone)]
Expand All @@ -16,6 +16,9 @@ pub struct Slot {
components_to_remove: Option<Vec<VarInt>>,
}




impl<'de> Deserialize<'de> for Slot {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
Expand Down Expand Up @@ -75,3 +78,20 @@ impl<'de> Deserialize<'de> for Slot {
deserializer.deserialize_seq(VarIntVisitor)
}
}
impl Slot {
pub fn to_item(self) -> Option<Item> {
let item_id = self.item_id?.0.try_into().unwrap();
Some(Item {
item_id,
item_count: self.item_count.0.try_into().unwrap(),
})
}
}
impl From<Slot> for Item {
fn from(slot: Slot) -> Self {
Item {
item_count: slot.item_count.0.try_into().unwrap(),
item_id: slot.item_id.unwrap().0.try_into().unwrap()
}
}
}
8 changes: 4 additions & 4 deletions pumpkin-world/src/block/block_registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,28 @@ use crate::level::WorldError;
const BLOCKS_JSON: &str = include_str!("../../assets/blocks.json");

#[derive(serde::Deserialize, Debug, Clone, PartialEq, Eq)]
struct BlockDefinition {
pub struct BlockDefinition {
#[serde(rename = "type")]
kind: String,
block_set_type: Option<String>,
}

#[derive(serde::Deserialize, Debug, Clone, PartialEq, Eq)]
struct BlockState {
pub struct BlockState {
default: Option<bool>,
id: i64,
properties: Option<HashMap<String, String>>,
}

#[derive(serde::Deserialize, Debug, Clone, PartialEq, Eq)]
struct BlocksElement {
pub struct BlocksElement {
definition: BlockDefinition,
properties: Option<HashMap<String, Vec<String>>>,
states: Vec<BlockState>,
}

lazy_static! {
static ref BLOCKS: HashMap<String, BlocksElement> =
pub static ref BLOCKS: HashMap<String, BlocksElement> =
serde_json::from_str(BLOCKS_JSON).expect("Could not parse block.json registry.");
}

Expand Down
2 changes: 1 addition & 1 deletion pumpkin-world/src/block/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use num_derive::FromPrimitive;
use crate::vector3::Vector3;

pub mod block_registry;

pub use block_registry::BLOCKS;
#[derive(FromPrimitive)]
pub enum BlockFace {
Bottom = 0,
Expand Down
15 changes: 12 additions & 3 deletions pumpkin-world/src/global_registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ const REGISTRY_JSON: &str = include_str!("../assets/registries.json");
#[derive(serde::Deserialize, Debug, Clone, PartialEq, Eq)]
pub struct RegistryElement {
default: Option<String>,
entries: HashMap<String, u32>,
pub entries: HashMap<String, HashMap<String,u32>>,
}

lazy_static! {
static ref REGISTRY: HashMap<String, RegistryElement> =
serde_json::from_str(REGISTRY_JSON).expect("Could not parse items.json registry.");
pub static ref REGISTRY: HashMap<String, RegistryElement> =
serde_json::from_str(REGISTRY_JSON).expect("Could not parse registry.json registry.");
}

pub fn get_protocol_id(category: &str, entry: &str) -> u32 {
Expand All @@ -23,6 +23,7 @@ pub fn get_protocol_id(category: &str, entry: &str) -> u32 {
.expect("Invalid Category in registry")
.entries
.get(entry)
.map(|p|p.get("protocol_id").unwrap())
.expect("No Entry found")
}

Expand All @@ -34,3 +35,11 @@ pub fn get_default<'a>(category: &str) -> Option<&'a str> {
.default
.as_deref()
}

pub fn find_minecraft_id(category: &str, protocol_id: u32) -> Option<&str> {
REGISTRY.get(category)?
.entries
.iter()
.find(|(_,other_protocol_id)|*other_protocol_id.get("protocol_id").unwrap()==protocol_id)
.map(|(id,_)|id.as_str())
}
75 changes: 75 additions & 0 deletions pumpkin-world/src/item/item_categories.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
use crate::item::Item;

impl Item {
pub fn is_helmet(&self) -> bool {
[
// Leather
856,
// Netherite
876,
// Turtle helmet
794,
// Chainmail
860,
// Diamond
868,
// Gold
872,
// Iron
864
].contains(&self.item_id)
}

pub fn is_chestplate(&self) -> bool {
[
// Leather
857,
// Netherite
877,
// Chainmail
861,
// Diamond
869,
// Gold
873,
// Iron
865,
// Elytra
773,
].contains(&self.item_id)
}

pub fn is_leggings(&self) -> bool {
[
// Leather
858,
// Netherite
878,
// Chainmail
862,
// Diamond
870,
// Gold
874,
// Iron
866
].contains(&self.item_id)
}

pub fn is_boots(&self) -> bool {
[
// Leather
859,
// Netherite
879,
// Chainmail
863,
// Diamond
871,
// Gold
875,
// Iron
867
].contains(&self.item_id)
}
}
8 changes: 4 additions & 4 deletions pumpkin-world/src/item/item_registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use lazy_static::lazy_static;

use crate::global_registry::{self, ITEM_REGISTRY};

use super::Raritiy;
use super::Rarity;

const ITEMS_JSON: &str = include_str!("../../assets/items.json");

Expand All @@ -17,18 +17,18 @@ pub struct ItemComponents {
#[serde(rename = "minecraft:max_stack_size")]
max_stack_size: u32,
#[serde(rename = "minecraft:rarity")]
rarity: Raritiy,
rarity: Rarity,
#[serde(rename = "minecraft:repair_cost")]
repair_cost: u32,
}

#[derive(serde::Deserialize, Debug, Clone, PartialEq, Eq)]
struct ItemElement {
pub struct ItemElement {
components: ItemComponents,
}

lazy_static! {
static ref ITEMS: HashMap<String, ItemElement> =
pub static ref ITEMS: HashMap<String, ItemElement> =
serde_json::from_str(ITEMS_JSON).expect("Could not parse items.json registry.");
}

Expand Down
14 changes: 10 additions & 4 deletions pumpkin-world/src/item/mod.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
mod item_registry;

mod item_categories;
pub use item_registry::ITEMS;
#[derive(serde::Deserialize, Debug, Clone, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
/// Item Raritiy
pub enum Raritiy {
/// Item Rarity
pub enum Rarity {
Common,
UnCommon,
Rare,
Epic,
}

#[derive(Clone, Copy)]
pub struct Item {}
pub struct Item {
pub item_count: u32,
// This ID is the numerical protocol ID, not the usual minecraft::block ID.
pub item_id: u32,
// TODO: Add Item Components
}
2 changes: 1 addition & 1 deletion pumpkin-world/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ pub const WORLD_HEIGHT: usize = 384;
pub const WORLD_Y_START_AT: i32 = -64;
pub const DIRECT_PALETTE_BITS: u32 = 15;
pub mod block;
mod global_registry;
pub mod global_registry;
pub mod item;
mod level;
pub mod radial_chunk_iterator;
Expand Down
Loading

0 comments on commit 5445975

Please sign in to comment.