Skip to content

Commit 6a0700b

Browse files
authored
Merge pull request #74 from ferrumc-rs/rewrite/v3_sweatyplams
ecs helper methods and outgoing #[packet] attribute
2 parents a6ab0d5 + a825b7f commit 6a0700b

File tree

29 files changed

+196
-68
lines changed

29 files changed

+196
-68
lines changed

src/bin/src/packet_handlers/handshake.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use ferrumc_net::errors::{NetError, PacketError};
55
use ferrumc_net::packets::incoming::handshake::HandshakeEvent;
66
use ferrumc_net::GlobalState;
77
use tracing::trace;
8+
use ferrumc_net::utils::ecs_helpers::EntityExt;
89

910
#[event_handler]
1011
async fn handle_handshake(
@@ -15,9 +16,9 @@ async fn handle_handshake(
1516
let handshake = &handshake_event.handshake;
1617

1718
// set connection state to handshake
18-
let mut connection_state = state
19-
.universe
20-
.get_mut::<ConnectionState>(handshake_event.conn_id)?;
19+
let entity = handshake_event.conn_id;
20+
let mut connection_state = entity
21+
.get_mut::<ConnectionState>(state)?;
2122

2223
trace!(
2324
"conn state: {} -> {}",
Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
use ferrumc_core::transform::position::Position;
22
use ferrumc_macros::event_handler;
33
use ferrumc_net::errors::NetError;
4-
use ferrumc_net::GlobalState;
54
use ferrumc_net::packets::incoming::set_player_position::SetPlayerPositionEvent;
5+
use ferrumc_net::GlobalState;
6+
use ferrumc_net::utils::ecs_helpers::EntityExt;
67

78
#[event_handler]
89
async fn handle_player_move(
@@ -12,11 +13,13 @@ async fn handle_player_move(
1213
let new_position = &event.data;
1314
let conn_id = event.conn_id;
1415

15-
let mut position = state
16-
.universe
17-
.get_mut::<Position>(conn_id)?;
18-
19-
*position = Position::new(new_position.x, new_position.feet_y, new_position.z);
20-
16+
let mut position = conn_id.get_mut::<Position>(state)?;
17+
18+
*position = Position::new(
19+
new_position.x,
20+
new_position.feet_y,
21+
new_position.z
22+
);
23+
2124
Ok(event)
2225
}

src/lib/core/src/identity/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub mod player_identity;
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#[derive(Debug)]
2+
pub struct PlayerIdentity {
3+
pub username: String,
4+
pub uuid: u128,
5+
}

src/lib/core/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ pub mod errors;
22

33

44
// Core structs/types. Usually used in ECS Components.
5-
pub mod transform;
5+
pub mod transform;
6+
pub mod identity;

src/lib/derive_macros/src/net/decode.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ pub(crate) fn derive(input: TokenStream) -> TokenStream {
6262
(type_cast, type_cast_handler)
6363
};
6464

65+
6566
// So for enums we can simply read the type and then cast it directly.
6667
if let Some(type_cast) = type_cast {
6768
let Some(repr_attr) = repr_attr else {

src/lib/derive_macros/src/net/encode.rs

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
use crate::helpers::StructInfo;
1+
use crate::helpers::{get_derive_attributes, StructInfo};
22
use proc_macro::TokenStream;
33
use quote::quote;
4-
use syn::{parse_macro_input, DeriveInput};
4+
use syn::{parse_macro_input, DeriveInput, LitInt};
55

66
pub(crate) fn derive(input: TokenStream) -> TokenStream {
77
let input = parse_macro_input!(input as DeriveInput);
@@ -12,6 +12,55 @@ pub(crate) fn derive(input: TokenStream) -> TokenStream {
1212
unimplemented!("NetEncode can only be derived for structs");
1313
};
1414

15+
let packet_attr = get_derive_attributes(&input, "packet");
16+
17+
let (packet_id_snippet, async_packet_id_snippet) = {
18+
let mut packet_id = None;
19+
packet_attr.iter().for_each(|attr| {
20+
attr.parse_nested_meta(|meta| {
21+
let Some(ident) = meta.path.get_ident() else {
22+
return Ok(());
23+
};
24+
25+
match ident.to_string().as_str() {
26+
"packet_id" => {
27+
let value = meta.value().expect("value failed");
28+
let value = value.parse::<LitInt>().expect("parse failed");
29+
let n = value.base10_parse::<u8>().expect("base10_parse failed");
30+
packet_id = Some(n);
31+
}
32+
&_ => {
33+
return Ok(());
34+
}
35+
}
36+
37+
Ok(())
38+
}).unwrap();
39+
});
40+
41+
let sync_impl = if let Some(packet_id) = packet_id {
42+
quote! {
43+
// encode a varint of packet_id
44+
// varint is at ferrumc_net_codec::net_types::var_int::VarInt
45+
<ferrumc_net_codec::net_types::var_int::VarInt as ferrumc_net_codec::encode::NetEncode>::encode(&#packet_id.into(), writer, &ferrumc_net_codec::encode::NetEncodeOpts::None)?;
46+
}
47+
} else {
48+
quote! { }
49+
};
50+
51+
let async_impl = if let Some(packet_id) = packet_id {
52+
quote! {
53+
// encode a varint of packet_id
54+
// varint is at ferrumc_net_codec::net_types::var_int::VarInt
55+
<ferrumc_net_codec::net_types::var_int::VarInt as ferrumc_net_codec::encode::NetEncode>::encode_async(&#packet_id.into(), writer, &ferrumc_net_codec::encode::NetEncodeOpts::None).await?;
56+
}
57+
} else {
58+
quote! { }
59+
};
60+
61+
(sync_impl, async_impl)
62+
};
63+
1564
let sync_encode_fields = fields.iter().map(|field| {
1665
let field_name = field.ident.as_ref().unwrap();
1766
let field_ty = &field.ty;
@@ -21,6 +70,7 @@ pub(crate) fn derive(input: TokenStream) -> TokenStream {
2170
}
2271
});
2372

73+
2474
let sync_impl = {
2575
// These exist only because we cannot move value LMAO, they're both the same
2676
let normal_fields = sync_encode_fields.clone();
@@ -31,6 +81,7 @@ pub(crate) fn derive(input: TokenStream) -> TokenStream {
3181
fn encode<W: std::io::Write>(&self, writer: &mut W, opts: &ferrumc_net_codec::encode::NetEncodeOpts) -> ferrumc_net_codec::encode::NetEncodeResult<()> {
3282
match opts {
3383
ferrumc_net_codec::encode::NetEncodeOpts::None => {
84+
#packet_id_snippet
3485
#(#normal_fields)*
3586
}
3687
ferrumc_net_codec::encode::NetEncodeOpts::WithLength => {
@@ -39,6 +90,7 @@ pub(crate) fn derive(input: TokenStream) -> TokenStream {
3990
let mut writer = &mut writer;
4091

4192

93+
#packet_id_snippet
4294
#(#length_prefixed_fields)*
4395

4496

@@ -60,6 +112,7 @@ pub(crate) fn derive(input: TokenStream) -> TokenStream {
60112
// Get compression threshold from config
61113
let compression_threshold = ferrumc_config::get_global_config().network_compression_threshold;
62114

115+
#packet_id_snippet
63116
#(#compressed_fields)*
64117

65118
// if size >= threshold, compress, otherwise, send uncompressed and set Data Length to 0
@@ -129,6 +182,7 @@ pub(crate) fn derive(input: TokenStream) -> TokenStream {
129182
async fn encode_async<W: tokio::io::AsyncWrite + std::marker::Unpin>(&self, writer: &mut W, opts: &ferrumc_net_codec::encode::NetEncodeOpts) -> ferrumc_net_codec::encode::NetEncodeResult<()> {
130183
match opts {
131184
ferrumc_net_codec::encode::NetEncodeOpts::None => {
185+
#async_packet_id_snippet
132186
#(#normal_fields)*
133187
}
134188
ferrumc_net_codec::encode::NetEncodeOpts::WithLength => {
@@ -137,6 +191,7 @@ pub(crate) fn derive(input: TokenStream) -> TokenStream {
137191
let mut writer = Vec::new();
138192
let mut writer = &mut writer;
139193

194+
#async_packet_id_snippet
140195
#(#length_prefixed_fields)*
141196

142197
let len: ferrumc_net_codec::net_types::var_int::VarInt = writer.len().into();
@@ -156,6 +211,7 @@ pub(crate) fn derive(input: TokenStream) -> TokenStream {
156211
// Get compression threshold from config
157212
let compression_threshold = ferrumc_config::get_global_config().network_compression_threshold;
158213

214+
#async_packet_id_snippet
159215
#(#compressed_fields)*
160216

161217
// if size >= threshold, compress, otherwise, send uncompressed and set Data Length to 0

src/lib/derive_macros/src/net/packets/mod.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ pub fn bake_registry(input: TokenStream) -> TokenStream {
142142
}
143143

144144

145-
/// `#[packet]` attribute is used to declare an incoming packet.
145+
/// `#[packet]` attribute is used to declare an incoming/outgoing packet.
146146
///
147147
/// <b>packet_id</b> => The packet id of the packet. In hexadecimal.
148148
/// <b>state</b> => The state of the packet. Can be: "handshake", "status", "login", "play".
@@ -158,12 +158,22 @@ pub fn bake_registry(input: TokenStream) -> TokenStream {
158158
/// pub timestamp: i64,
159159
/// }
160160
/// ```
161+
///
162+
/// ```
163+
/// use ferrumc_macros::NetEncode;
164+
///
165+
/// #[derive(NetEncode)]
166+
/// #[packet(packet_id = 0x05)]
167+
/// pub struct PacketChatMessage {
168+
/// pub message: String,
169+
/// pub timestamp: i64,
170+
/// }
161171
pub fn attribute(args: TokenStream, input: TokenStream) -> TokenStream {
162172
// These are just some checks to make sure the packet attribute is used correctly.
163173
// This is not actual functionality.
164174
// The actual functionality is in the `bake_registry` function.
165175

166-
const E: &str = "packet attribute must have the packet_id and state fields";
176+
const E: &str = "packet attribute must have the packet_id and/or state fields. In case of incoming: both. In case of outgoing: only packet_id.";
167177
if args.is_empty() {
168178
return TokenStream::from(quote! {
169179
compile_error!(#E);
@@ -172,7 +182,7 @@ pub fn attribute(args: TokenStream, input: TokenStream) -> TokenStream {
172182

173183
if !&["packet_id", "state"]
174184
.iter()
175-
.all(|x| args.to_string().contains(x))
185+
.any(|x| args.to_string().contains(x))
176186
{
177187
return TokenStream::from(quote! {
178188
compile_error!(#E);

src/lib/ecs/src/components/mod.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,22 @@ pub struct ComponentRefMut<'a, T: Component> {
123123
write_guard: RwLockWriteGuard<'a, Box<dyn Component>>,
124124
_phantom: PhantomData<&'a mut T>,
125125
}
126+
mod debug {
127+
use std::fmt::Debug;
128+
use crate::components::{Component, ComponentRef, ComponentRefMut};
129+
130+
impl<'a, T: Component + Debug> Debug for ComponentRef<'a, T> {
131+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
132+
Debug::fmt(&**self, f)
133+
}
134+
}
135+
136+
impl<'a, T: Component + Debug> Debug for ComponentRefMut<'a, T> {
137+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
138+
Debug::fmt(&**self, f)
139+
}
140+
}
141+
}
126142

127143
impl<'a, T: Component> Deref for ComponentRef<'a, T> {
128144
type Target = T;

src/lib/events/src/infrastructure.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ pub trait Event: Sized + Send + Sync + 'static {
8181

8282
// Convert listeners iterator into Stream
8383
stream::iter(listeners.iter())
84+
// TODO: Remove this since it's not possible to have a wrong type in the map of the event???
85+
// Maybe some speedup?
8486
// Filter only listeners we can downcast into the correct type
8587
.filter_map(
8688
|dyn_list| async { dyn_list.downcast_ref::<EventListener<Self>>() },

0 commit comments

Comments
 (0)