Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(core) Packet implementations #10

Merged
merged 9 commits into from
Sep 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ once_cell = "1.18"
serde = { version = "1.0", features = ["serde_derive"] }
serde_json = "1.0"
toml = "0.8"
uuid = { version = "1.3", features = ["v3", "v4"] }
uuid = { version = "1.4", features = ["v3", "v4"] }
md-5 = "0.10"
url = "2.4"
sysinfo = "0.29"
Expand All @@ -28,3 +28,4 @@ cesu8 = "*"
dashmap = "5.4"
bimap = "0.6"
thiserror = "1.0"
rsa = "0.9"
4 changes: 4 additions & 0 deletions core/src/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ impl Components {
///
/// To create with external features,
/// see [`Self::builder()`].
#[inline]
pub fn new() -> Self {
Default::default()
}
Expand Down Expand Up @@ -256,6 +257,7 @@ impl<T> Encode for Component<T>
where
T: Encode,
{
#[inline]
fn encode<B>(&self, buf: &mut B) -> anyhow::Result<()>
where
B: bytes::BufMut,
Expand Down Expand Up @@ -396,6 +398,7 @@ impl<T> Encode for Synced<T>
where
T: Attach + NetSync + 'static,
{
#[inline]
fn encode<B>(&self, buf: &mut B) -> anyhow::Result<()>
where
B: bytes::BufMut,
Expand Down Expand Up @@ -570,6 +573,7 @@ impl<T> Encode for Stored<T>
where
T: Attach + crate::nbt::Update + Encode + 'static,
{
#[inline]
fn encode<B>(&self, buf: &mut B) -> anyhow::Result<()>
where
B: bytes::BufMut,
Expand Down
71 changes: 12 additions & 59 deletions core/src/item/event.rs
Original file line number Diff line number Diff line change
@@ -1,59 +1,12 @@
use crate::registry::Registration;

/// Core item events for perform item actions and obtain item settings.
pub static EVENTS: parking_lot::RwLock<Events> = parking_lot::RwLock::new(Events(vec![]));

/// Manager for item events.
pub struct Events(Vec<(Option<usize>, Callback)>);

impl Events {
/// Register a callback into this instance.
///
/// The required `item` can be `None` for some events
/// so that all items will be affected by this callback.
pub fn register(&mut self, item: Option<super::Item>, callback: Callback) {
self.0.push((item.map(|e| e.raw_id()), callback));
}

pub fn get_max_damage(&self, stack: &super::ItemStack) -> u32 {
let id = stack.item.raw_id();
self.0
.iter()
.find(|e| e.0.map_or(false, |ee| ee == id) && matches!(e.1, Callback::GetMaxDamage(_)))
.map_or(0, |e| match &e.1 {
Callback::GetMaxDamage(c) => c(stack),
_ => unreachable!(),
})
}

pub fn get_max_count(&self, stack: &super::ItemStack) -> u8 {
let id = stack.item.raw_id();
self.0
.iter()
.find(|e| e.0.map_or(false, |ee| ee == id) && matches!(e.1, Callback::GetMaxCount(_)))
.map_or(64, |e| match &e.1 {
Callback::GetMaxCount(c) => c(stack),
_ => unreachable!(),
})
}

pub fn post_process_nbt(&self, item: super::Item, nbt: &mut crate::nbt::NbtCompound) {
let id = item.raw_id();
self.0
.iter()
.filter(|e| {
e.0.map_or(true, |ee| ee == id) && matches!(e.1, Callback::PostProcessNbt(_))
})
.for_each(|e| match &e.1 {
Callback::PostProcessNbt(c) => c(nbt),
_ => unreachable!(),
})
}
}

/// An item event callback variant.
pub enum Callback {
GetMaxCount(fn(&super::ItemStack) -> u8),
GetMaxDamage(fn(&super::ItemStack) -> u32),
PostProcessNbt(fn(&mut crate::nbt::NbtCompound)),
}
use crate::util::Event;

use super::Item;

pub static POST_PROCESS_NBT: Event<dyn Fn(Item, &mut crate::nbt::NbtCompound)> =
Event::new(|listeners| {
Box::new(move |item, nbt| {
for listener in listeners {
listener(item, nbt)
}
})
});
45 changes: 37 additions & 8 deletions core/src/item/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,35 @@ pub struct Item {
}

/// Describes some basic properties of an item.
#[derive(Clone, Copy)]
pub struct ItemDescriptor {
pub sync_nbt: bool,
pub max_damage: u32,
pub max_count: u8,
pub components: crate::component::Components,
}

impl Default for ItemDescriptor {
#[inline]
fn default() -> Self {
Self { sync_nbt: true }
Self {
sync_nbt: true,
max_damage: 0,
max_count: 64,
components: crate::component::Components::new(),
}
}
}

impl Item {
#[inline]
pub fn new(descriptor: ItemDescriptor) -> Self {
Self {
id: 0,
properties: descriptor.into(),
}
}

#[inline]
pub fn descriptor(&self) -> &ItemDescriptor {
&self.properties
}
Expand Down Expand Up @@ -79,7 +89,7 @@ impl<'de> serde::Deserialize<'de> for Item {
let id = Id::deserialize(deserializer)?;
Ok(crate::registry::ITEM.get_from_id(&id).map_or_else(
|| {
tracing::debug!("Tried to load invalid item: {id}");
tracing::debug!("tried to load invalid item: {id}");
crate::registry::ITEM.default_entry().1.as_item()
},
|e| *e.1.deref(),
Expand Down Expand Up @@ -151,6 +161,7 @@ impl ItemStack {
const UNBREAKABLE_KEY: &str = "Unbreakable";
const DAMAGE_KEY: &str = "Damage";

#[inline]
pub fn new(item: &impl AsItem, count: u8) -> Self {
Self {
count,
Expand All @@ -160,6 +171,7 @@ impl ItemStack {
}

/// Whether this item stack is empty.
#[inline]
pub fn is_empty(&self) -> bool {
self.item == Item::default() || self.count == 0
}
Expand All @@ -175,11 +187,13 @@ impl ItemStack {
}

/// Take all items from this stack into a new stack.
#[inline]
pub fn take_all(&mut self) -> Self {
self.take(self.count)
}

/// Get [`Item`] inside this stack.
#[inline]
pub fn item(&self) -> Item {
self.item
}
Expand All @@ -191,40 +205,47 @@ impl ItemStack {
.unwrap())
}

#[inline]
pub fn nbt(&self) -> Option<&crate::nbt::NbtCompound> {
self.nbt.as_ref()
}

#[inline]
pub fn nbt_mut(&mut self) -> Option<&mut crate::nbt::NbtCompound> {
self.nbt.as_mut()
}

#[inline]
pub fn get_or_init_nbt(&mut self) -> &mut crate::nbt::NbtCompound {
self.nbt
.get_or_insert_with(|| crate::nbt::NbtCompound::new())
}

pub fn set_nbt(&mut self, nbt: Option<crate::nbt::NbtCompound>) {
self.nbt = nbt;

if self.is_damageable() {
self.set_damage(self.damage());
}

if let Some(nbt) = &mut self.nbt {
EVENTS.read().post_process_nbt(self.item, nbt);
if let Some(ref mut nbt) = self.nbt {
POST_PROCESS_NBT.invoker()(self.item, nbt);
}
}

#[inline]
pub fn max_count(&self) -> u8 {
EVENTS.read().get_max_count(self)
self.item().descriptor().max_count
}

#[inline]
pub fn is_stackable(&self) -> bool {
self.max_count() > 1
}

#[inline]
pub fn max_damage(&self) -> u32 {
EVENTS.read().get_max_damage(self)
self.item().descriptor().max_damage
}

pub fn is_damageable(&self) -> bool {
Expand All @@ -237,17 +258,20 @@ impl ItemStack {
}
}

#[inline]
pub fn is_damaged(&self) -> bool {
self.is_damageable() && self.damage() > 0
}

/// Get damage of this satck from the nbt tags.
#[inline]
pub fn damage(&self) -> u32 {
self.nbt.as_ref().map_or(0, |nbt| {
nbt.get_i32(Self::DAMAGE_KEY).unwrap_or_default() as u32
})
}

#[inline]
pub fn set_damage(&mut self, damage: u32) {
self.get_or_init_nbt()
.insert_i32(Self::DAMAGE_KEY, damage as i32);
Expand Down Expand Up @@ -286,22 +310,27 @@ impl<'de> serde::Deserialize<'de> for ItemStack {
{
let mut raw = RawItemStack::deserialize(deserializer)?;
let item = raw.id;

if let Some(nbt) = &mut raw.tag {
EVENTS.read().post_process_nbt(item, nbt);
POST_PROCESS_NBT.invoker()(item, nbt);
}

let mut stack = Self {
count: raw.count as u8,
item: raw.id,
nbt: raw.tag,
};

if stack.is_damageable() {
stack.set_damage(stack.damage());
}

Ok(stack)
}
}

impl AsItem for ItemStack {
#[inline]
fn as_item(&self) -> Item {
self.item()
}
Expand Down
1 change: 1 addition & 0 deletions core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ pub mod net;
pub mod registry;
pub mod server;
pub mod state;
pub mod text;
mod util;
pub mod world;

Expand Down
Empty file added core/src/net/encrypt.rs
Empty file.
35 changes: 35 additions & 0 deletions core/src/net/listener.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use crate::text::Text;

pub trait Listener {
const SHOULD_CRASH_ON_EXCEPTION: bool;

fn disconncted<T>(&mut self, reason: T) -> anyhow::Result<()>
where
T: Text;

fn is_conn_open(&self) -> bool;
}

/// Represent [`Listener`] types that are able to accept
/// a certain type of packet when applying it.
pub trait Accept<T: ?Sized>: Listener
where
T: super::packet::Packet<Self>,
{
/// Accept the packet.
fn accept_packet(&mut self, packet: &T) -> anyhow::Result<()>;
}

impl<T> Accept<()> for T
where
T: Listener,
{
#[inline]
fn accept_packet(&mut self, _packet: &()) -> anyhow::Result<()> {
Ok(())
}
}

pub trait Tick: Listener {
fn tick(&mut self);
}
Loading