Skip to content

Commit

Permalink
Item Components 👀
Browse files Browse the repository at this point in the history
  • Loading branch information
Outspending committed Jan 9, 2025
1 parent 2db4348 commit 4749a81
Show file tree
Hide file tree
Showing 10 changed files with 167 additions and 58 deletions.
6 changes: 3 additions & 3 deletions src/bin/src/packet_handlers/containers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ async fn handle_container_click(
let slot_num = changed_slot.slot_number;

inventory
.set_slot(slot_num, Slot::from_network_slot(changed_slot.slot))
.set_slot(slot_num, Slot::from_network_slot(&changed_slot.slot))
.sync_inventory(conn_id, &InventorySyncType::Single(slot_num), state)
.await
.map_err(|err| NetError::Other(err.to_string()))?;
Expand All @@ -54,7 +54,7 @@ async fn handle_container_click(
changed_slots.iter().for_each(|changed_slot| {
inventory.set_slot(
changed_slot.slot_number,
Slot::from_network_slot(changed_slot.slot),
Slot::from_network_slot(&changed_slot.slot),
);
});

Expand All @@ -79,7 +79,7 @@ async fn set_creative_mode_slot(
let mut inventory = state.universe.get_mut::<PlayerInventory>(conn_id)?;
inventory.set_slot(
creative_mode_slot.slot,
Slot::from_network_slot(creative_mode_slot.clicked_item),
Slot::from_network_slot(&creative_mode_slot.clicked_item),
);

Ok(creative_mode_slot)
Expand Down
2 changes: 1 addition & 1 deletion src/lib/inventory/src/contents.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{inventory::InventoryType, slot::Slot};
use ferrumc_net::packets::outgoing::set_container_slot::NetworkSlot;
use ferrumc_net::slot::NetworkSlot;
use ferrumc_net_codec::net_types::length_prefixed_vec::LengthPrefixedVec;
use std::collections::BTreeMap;

Expand Down
4 changes: 2 additions & 2 deletions src/lib/inventory/src/slot.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use ferrumc_net::packets::outgoing::set_container_slot::NetworkSlot;
use ferrumc_net::slot::NetworkSlot;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Slot {
Expand Down Expand Up @@ -37,7 +37,7 @@ impl Slot {
Self::new(0, 0)
}

pub fn from_network_slot(slot: NetworkSlot) -> Self {
pub fn from_network_slot(slot: &NetworkSlot) -> Self {
match slot.item_id {
Some(item) => Self::new(*slot.item_count, *item),
None => Self::empty(),
Expand Down
2 changes: 2 additions & 0 deletions src/lib/net/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ pub mod connection;
pub mod errors;
pub mod packets;
pub mod server;
pub mod slot;
pub mod utils;

pub type NetResult<T> = Result<T, errors::NetError>;

bake_packet_registry!("\\src\\packets\\incoming");
2 changes: 1 addition & 1 deletion src/lib/net/src/packets/incoming/click_container.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::packets::outgoing::set_container_slot::NetworkSlot;
use crate::packets::IncomingPacket;
use crate::slot::NetworkSlot;
use crate::NetResult;
use ferrumc_events::infrastructure::Event;
use ferrumc_macros::{packet, Event, NetDecode};
Expand Down
5 changes: 1 addition & 4 deletions src/lib/net/src/packets/incoming/set_creative_mode_slot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@ use ferrumc_events::infrastructure::Event;
use ferrumc_macros::{packet, Event, NetDecode};
use ferrumc_state::ServerState;

use crate::{
packets::{outgoing::set_container_slot::NetworkSlot, IncomingPacket},
NetResult,
};
use crate::{packets::IncomingPacket, slot::NetworkSlot, NetResult};

#[derive(NetDecode, Debug)]
#[packet(packet_id = "set_creative_mode_slot", state = "play")]
Expand Down
3 changes: 2 additions & 1 deletion src/lib/net/src/packets/outgoing/set_container_content.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use super::set_container_slot::NetworkSlot;
use ferrumc_macros::{packet, NetEncode};
use ferrumc_net_codec::net_types::{length_prefixed_vec::LengthPrefixedVec, var_int::VarInt};
use std::io::Write;

use crate::slot::NetworkSlot;

#[derive(NetEncode, Debug)]
#[packet(packet_id = "container_set_content", state_id = "play")]
pub struct SetContainerContentPacket {
Expand Down
42 changes: 2 additions & 40 deletions src/lib/net/src/packets/outgoing/set_container_slot.rs
Original file line number Diff line number Diff line change
@@ -1,46 +1,8 @@
use ferrumc_macros::{packet, NetDecode, NetEncode};
use ferrumc_macros::{packet, NetEncode};
use ferrumc_net_codec::net_types::var_int::VarInt;
use std::io::Write;

#[derive(NetDecode, NetEncode, Debug, Clone, Copy)]
pub struct NetworkSlot {
pub item_count: VarInt,
#[net(optional_trigger = *item_count > 0)]
pub item_id: Option<VarInt>,
#[net(optional_trigger = *item_count > 0)]
pub num_of_components_to_add: Option<VarInt>,
#[net(optional_trigger = *item_count > 0)]
pub num_of_components_to_remove: Option<VarInt>,
}

impl NetworkSlot {
pub fn new(item_count: i32, item_id: i32) -> Self {
let components = if item_count == 0 {
None
} else {
Some(VarInt::new(0))
};
Self {
item_count: VarInt::new(item_count),
item_id: if item_count == 0 {
None
} else {
Some(VarInt::new(item_id))
},
num_of_components_to_add: components,
num_of_components_to_remove: components,
}
}

pub fn empty() -> Self {
Self::new(0, 0)
}

pub fn item_id(&mut self, item_id: VarInt) -> &mut Self {
self.item_id = Some(item_id);
self
}
}
use crate::slot::NetworkSlot;

#[derive(NetEncode)]
#[packet(packet_id = "container_set_slot", state_id = "play")]
Expand Down
2 changes: 1 addition & 1 deletion src/lib/net/src/packets/outgoing/set_equipment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use ferrumc_net_codec::{
};
use std::io::Write;

use super::set_container_slot::NetworkSlot;
use crate::slot::NetworkSlot;

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum EquipmentSlot {
Expand Down
157 changes: 152 additions & 5 deletions src/lib/net/src/slot.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,171 @@
use std::io::Read;
use std::io::{Read, Write};

use ferrumc_macros::{NetDecode, NetEncode};
use ferrumc_net_codec::{
decode::{NetDecode, NetDecodeOpts, NetDecodeResult},
decode::{errors::NetDecodeError, NetDecode, NetDecodeOpts, NetDecodeResult},
encode::{NetEncode, NetEncodeOpts, NetEncodeResult},
net_types::{length_prefixed_vec::LengthPrefixedVec, var_int::VarInt},
};
use tokio::io::AsyncWrite;

#[derive(NetEncode, Debug, Clone, Copy)]
#[derive(Debug, Clone, Copy)]
pub enum SlotComponent {
MaxStackSize { max_stack_size: VarInt },
}

#[derive(Debug, Clone, Copy)]
impl NetEncode for SlotComponent {
fn encode<W: Write>(&self, writer: &mut W, opts: &NetEncodeOpts) -> NetEncodeResult<()> {
VarInt::new(self.get_type()).encode(writer, opts)?;
match self {
SlotComponent::MaxStackSize { max_stack_size } => {
max_stack_size.encode(writer, opts)?;
}
};

Ok(())
}

async fn encode_async<W: AsyncWrite + Unpin>(
&self,
writer: &mut W,
opts: &NetEncodeOpts,
) -> NetEncodeResult<()> {
VarInt::new(self.get_type())
.encode_async(writer, opts)
.await?;
match self {
SlotComponent::MaxStackSize { max_stack_size } => {
max_stack_size.encode_async(writer, opts).await?;
}
};

Ok(())
}
}

impl NetDecode for SlotComponent {
fn decode<R: Read>(reader: &mut R, opts: &NetDecodeOpts) -> NetDecodeResult<Self> {
let id = VarInt::decode(reader, opts)?;
match *id {
1 => Ok(SlotComponent::MaxStackSize {
max_stack_size: VarInt::decode(reader, opts)?,
}),
_ => Err(NetDecodeError::InvalidEnumVariant),
}
}
}

impl SlotComponent {
pub fn get_type(&self) -> i32 {
match self {
SlotComponent::MaxStackSize { .. } => 1,
}
}
}

#[derive(Debug)]
pub struct NetworkSlot {
pub item_count: VarInt,
pub item_id: Option<VarInt>,
pub components_to_add: Option<LengthPrefixedVec<SlotComponent>>,
pub components_to_remove: Option<LengthPrefixedVec<VarInt>>,
}

impl NetEncode for NetworkSlot {
fn encode<W: Write>(&self, writer: &mut W, opts: &NetEncodeOpts) -> NetEncodeResult<()> {
self.item_count.encode(writer, opts)?;

if let Some(id) = self.item_id {
id.encode(writer, opts)?;
}

match (&self.components_to_add, &self.components_to_remove) {
(Some(components_add), Some(components_remove)) => {
components_add.length.encode(writer, opts)?;
components_remove.length.encode(writer, opts)?;

for component in &components_add.data {
component.encode(writer, opts)?;
}

for component in &components_remove.data {
component.encode(writer, opts)?;
}
}
_ => {} // Do nothing if both components are None
}

Ok(())
}

async fn encode_async<W: AsyncWrite + Unpin>(
&self,
writer: &mut W,
opts: &NetEncodeOpts,
) -> NetEncodeResult<()> {
self.item_count.encode_async(writer, opts).await?;

if let Some(id) = self.item_id {
id.encode_async(writer, opts).await?;
}

match (&self.components_to_add, &self.components_to_remove) {
(Some(components_add), Some(components_remove)) => {
components_add.length.encode_async(writer, opts).await?;
components_remove.length.encode_async(writer, opts).await?;

for component in &components_add.data {
component.encode_async(writer, opts).await?;
}

for component in &components_remove.data {
component.encode_async(writer, opts).await?;
}
}
_ => {} // Do nothing if both components are None
}

Ok(())
}
}

impl NetDecode for NetworkSlot {
fn decode<R: Read>(reader: &mut R, opts: &NetDecodeOpts) -> NetDecodeResult<Self> {
let item_count = VarInt::decode(reader, opts)?;

if item_count == 0 {
return Ok(NetworkSlot::empty());
}

let item_id = VarInt::decode(reader, opts)?;

let mut components_to_add = Vec::with_capacity(*VarInt::decode(reader, opts)? as usize);
let mut components_to_remove = Vec::with_capacity(*VarInt::decode(reader, opts)? as usize);

for _ in 0..components_to_add.capacity() {
components_to_add.push(SlotComponent::decode(reader, opts)?);
}

for _ in 0..components_to_remove.capacity() {
components_to_remove.push(VarInt::decode(reader, opts)?);
}

Ok(Self {
item_count,
item_id: Some(item_id),
components_to_add: if components_to_add.is_empty() {
None
} else {
Some(LengthPrefixedVec::new(components_to_add))
},
components_to_remove: if components_to_remove.is_empty() {
None
} else {
Some(LengthPrefixedVec::new(components_to_remove))
},
})
}
}

impl NetworkSlot {
pub fn new(item_count: i32, item_id: i32) -> Self {
Self::with_components(item_count, item_id, vec![])
Expand Down

0 comments on commit 4749a81

Please sign in to comment.