honestly fixed so much and forgot to commit

Signed-off-by: Sienna Meridian Satterwhite <sienna@r3t.io>
This commit is contained in:
2025-12-28 17:39:27 +00:00
parent 28909e8b76
commit e890b0213a
47 changed files with 2248 additions and 438 deletions

View File

@@ -5,6 +5,7 @@ mod as_bind_group;
mod extract_component;
mod extract_resource;
mod specializer;
mod synced;
use bevy_macro_utils::{derive_label, BevyManifest};
use proc_macro::TokenStream;
@@ -150,3 +151,26 @@ pub fn derive_draw_function_label(input: TokenStream) -> TokenStream {
.push(format_ident!("DrawFunctionLabel").into());
derive_label(input, "DrawFunctionLabel", &trait_path)
}
/// Attribute macro for automatic component synchronization.
///
/// Automatically generates Component, rkyv serialization derives, and registers
/// the component in the ComponentTypeRegistry for network synchronization.
///
/// # Example
///
/// ```no_compile
/// use macros::synced;
///
/// #[synced]
/// pub struct CubeMarker {
/// pub color_r: f32,
/// pub color_g: f32,
/// pub color_b: f32,
/// pub size: f32,
/// }
/// ```
#[proc_macro_attribute]
pub fn synced(attr: TokenStream, item: TokenStream) -> TokenStream {
synced::synced_attribute(attr, item)
}

View File

@@ -0,0 +1,57 @@
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, DeriveInput};
pub fn synced_attribute(_attr: TokenStream, item: TokenStream) -> TokenStream {
let ast = parse_macro_input!(item as DeriveInput);
let struct_name = &ast.ident;
let vis = &ast.vis;
let attrs = &ast.attrs;
let generics = &ast.generics;
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
let fields = match &ast.data {
syn::Data::Struct(data) => &data.fields,
_ => panic!("#[synced] can only be used on structs"),
};
TokenStream::from(quote! {
// Generate the struct with all necessary derives
#(#attrs)*
#[derive(::bevy::prelude::Component, Clone, Copy, Debug)]
#[derive(::rkyv::Archive, ::rkyv::Serialize, ::rkyv::Deserialize)]
#vis struct #struct_name #generics #fields
// Register component in type registry using inventory
::inventory::submit! {
::libmarathon::persistence::ComponentMeta {
type_name: stringify!(#struct_name),
type_path: concat!(module_path!(), "::", stringify!(#struct_name)),
type_id: std::any::TypeId::of::<#struct_name>(),
deserialize_fn: |bytes: &[u8]| -> anyhow::Result<Box<dyn std::any::Any>> {
let component = ::rkyv::from_bytes::<#struct_name #ty_generics, ::rkyv::rancor::Failure>(bytes)?;
Ok(Box::new(component))
},
serialize_fn: |world: &::bevy::ecs::world::World, entity: ::bevy::ecs::entity::Entity|
-> Option<::bytes::Bytes>
{
world.get::<#struct_name #ty_generics>(entity).map(|component| {
let serialized = ::rkyv::to_bytes::<::rkyv::rancor::Failure>(component)
.expect("Failed to serialize component");
::bytes::Bytes::from(serialized.to_vec())
})
},
insert_fn: |entity_mut: &mut ::bevy::ecs::world::EntityWorldMut,
boxed: Box<dyn std::any::Any>|
{
if let Ok(component) = boxed.downcast::<#struct_name #ty_generics>() {
entity_mut.insert(*component);
}
},
}
}
})
}