diff --git a/Cargo.lock b/Cargo.lock index 7eef5604..1c77d068 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2932,6 +2932,14 @@ dependencies = [ "uuid", ] +[[package]] +name = "hyperion-plugin-channel" +version = "0.1.0" +dependencies = [ + "flecs_ecs", + "hyperion", +] + [[package]] name = "hyperion-proto" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 9bbe435a..317116f3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,6 +30,7 @@ members = [ 'crates/hyperion-nerd-font', 'crates/hyperion-palette', 'crates/hyperion-permission', + 'crates/hyperion-plugin-channel', 'crates/hyperion-proto', 'crates/hyperion-proxy', 'crates/hyperion-rank-tree', @@ -183,6 +184,9 @@ path = 'crates/hyperion-palette' [workspace.dependencies.hyperion-permission] path = 'crates/hyperion-permission' +[workspace.dependencies.hyperion-plugin-channel] +path = 'crates/hyperion-plugin-channel' + [workspace.dependencies.hyperion-proto] path = 'crates/hyperion-proto' diff --git a/crates/hyperion-clap/src/lib.rs b/crates/hyperion-clap/src/lib.rs index 18c521d3..331934b2 100644 --- a/crates/hyperion-clap/src/lib.rs +++ b/crates/hyperion-clap/src/lib.rs @@ -8,7 +8,7 @@ use flecs_ecs::{ use hyperion::{ net::{Compose, ConnectionId, DataBundle, agnostic}, simulation::{IgnMap, command::get_root_command_entity, handlers::PacketSwitchQuery}, - storage::{CommandCompletionRequest, EventFn}, + storage::{CommandCompletionRequest, BoxedEventFn}, }; pub use hyperion_clap_macros::CommandPermission; pub use hyperion_command; @@ -111,7 +111,7 @@ pub trait MinecraftCommand: Parser + CommandPermission { }; }; - let on_tab_complete: EventFn> = Box::new( + let on_tab_complete: BoxedEventFn> = Box::new( |packet_switch_query: &mut PacketSwitchQuery<'_>, completion: &CommandCompletionRequest<'_>| { let full_query = completion.query; diff --git a/crates/hyperion-command/src/component.rs b/crates/hyperion-command/src/component.rs index b35e2bbe..2d8f0cff 100644 --- a/crates/hyperion-command/src/component.rs +++ b/crates/hyperion-command/src/component.rs @@ -3,12 +3,12 @@ use flecs_ecs::{ macros::Component, prelude::Module, }; -use hyperion::storage::{CommandCompletionRequest, EventFn}; +use hyperion::storage::{CommandCompletionRequest, BoxedEventFn}; use indexmap::IndexMap; pub struct CommandHandler { pub on_execute: fn(input: &str, system: EntityView<'_>, caller: Entity), - pub on_tab_complete: EventFn>, + pub on_tab_complete: BoxedEventFn>, pub has_permissions: fn(world: &World, caller: Entity) -> bool, } diff --git a/crates/hyperion-item/src/lib.rs b/crates/hyperion-item/src/lib.rs index 5a6a25d9..b74418f2 100644 --- a/crates/hyperion-item/src/lib.rs +++ b/crates/hyperion-item/src/lib.rs @@ -4,7 +4,7 @@ use flecs_ecs::{ macros::Component, prelude::Module, }; -use hyperion::storage::{EventFn, GlobalEventHandlers, InteractEvent}; +use hyperion::storage::{BoxedEventFn, GlobalEventHandlers, InteractEvent}; use valence_protocol::nbt; pub mod builder; @@ -14,7 +14,7 @@ pub struct ItemModule; #[derive(Component, Constructor, Deref, DerefMut)] pub struct Handler { - on_click: EventFn, + on_click: BoxedEventFn, } impl Module for ItemModule { diff --git a/crates/hyperion-plugin-channel/.gitignore b/crates/hyperion-plugin-channel/.gitignore new file mode 100644 index 00000000..ea8c4bf7 --- /dev/null +++ b/crates/hyperion-plugin-channel/.gitignore @@ -0,0 +1 @@ +/target diff --git a/crates/hyperion-plugin-channel/Cargo.toml b/crates/hyperion-plugin-channel/Cargo.toml new file mode 100644 index 00000000..57db0d85 --- /dev/null +++ b/crates/hyperion-plugin-channel/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "hyperion-plugin-channel" +version.workspace = true +edition.workspace = true +authors = ["Andrew Gazelka "] +readme = "README.md" +publish = false + +[dependencies] +flecs_ecs.workspace = true +hyperion.workspace = true + +[lints] +workspace = true diff --git a/crates/hyperion-plugin-channel/README.md b/crates/hyperion-plugin-channel/README.md new file mode 100644 index 00000000..53ea886b --- /dev/null +++ b/crates/hyperion-plugin-channel/README.md @@ -0,0 +1 @@ +# hyperion-plugin-channel \ No newline at end of file diff --git a/crates/hyperion-plugin-channel/src/lib.rs b/crates/hyperion-plugin-channel/src/lib.rs new file mode 100644 index 00000000..bf641c43 --- /dev/null +++ b/crates/hyperion-plugin-channel/src/lib.rs @@ -0,0 +1,90 @@ +use std::collections::HashMap; + +use flecs_ecs::{ + core::{QueryBuilderImpl, SystemAPI, TermBuilderImpl, World}, + macros::{Component, system}, + prelude::Module, +}; +use hyperion::{ + HyperionCore, + simulation::event::PluginMessage, + storage::{BoxedEventFn, EventFn, EventQueue}, + valence_ident::Ident, +}; + +#[derive(Component)] +struct PluginChannelModule; + +#[derive(Component, Default)] +struct PluginChannelRegistry { + registry: HashMap, BoxedEventFn<[u8]>>, +} + +impl PluginChannelRegistry { + pub fn register(&mut self, name: impl Into>, handler: impl EventFn<[u8]>) { + let name = name.into(); + self.registry.insert(name, EventFn::boxed(handler)); + } +} + +impl Module for PluginChannelModule { + fn module(world: &World) { + world.import::(); + + world.component::(); + world.add::(); + + system!( + "process-plugin-messages", + world, + &mut EventQueue>($), + &PluginChannelRegistry($) + ) + .each_iter(|it, _, (queue, registry)| { + for PluginMessage { channel, data } in queue.drain() { + let Some(handler) = registry.registry.get(channel) else { + continue; + }; + + handler(todo!(), data); + } + }); + // world.get::<&mut EventQueue>>(move |queue| + // for PluginMessage { channel, data } in queue.drain() { + + // } + // }); + } +} + +#[cfg(test)] +mod tests { + use flecs_ecs::core::WorldGet; + use hyperion::{ + valence_ident::ident, + valence_protocol::{RawBytes, packets::play}, + }; + + use super::*; + + #[test] + fn test_echo() { + let world = World::new(); + world.import::(); + + world.get::<&mut PluginChannelRegistry>(|registry| { + registry.register(ident!("hyperion:echo"), |query, data| { + let data = RawBytes::from(data); + let response_packet = play::CustomPayloadS2c { + channel: ident!("hyperion:echo").into(), + data: data.into(), + }; + + query + .compose + .unicast(&response_packet, query.io_ref, query.system) + .unwrap(); + }); + }); + } +} diff --git a/crates/hyperion-rank-tree/src/lib.rs b/crates/hyperion-rank-tree/src/lib.rs index eed3d585..3ef7b9a4 100644 --- a/crates/hyperion-rank-tree/src/lib.rs +++ b/crates/hyperion-rank-tree/src/lib.rs @@ -6,7 +6,7 @@ use flecs_ecs::{ }; use hyperion::{ simulation::{Player, handlers::PacketSwitchQuery}, - storage::{EventFn, InteractEvent}, + storage::{BoxedEventFn, InteractEvent}, }; pub mod inventory; @@ -66,7 +66,7 @@ impl Module for RankTree { .component::() .add_trait::<(flecs::With, Class)>(); - let handler: EventFn = Box::new(|query: &mut PacketSwitchQuery<'_>, _| { + let handler: BoxedEventFn = Box::new(|query: &mut PacketSwitchQuery<'_>, _| { let cursor = query.inventory.get_cursor(); tracing::debug!("clicked {cursor:?}"); }); diff --git a/crates/hyperion/src/storage/event/sync.rs b/crates/hyperion/src/storage/event/sync.rs index 0ef81b2f..bf063ac7 100644 --- a/crates/hyperion/src/storage/event/sync.rs +++ b/crates/hyperion/src/storage/event/sync.rs @@ -10,7 +10,19 @@ use valence_protocol::{ use crate::simulation::handlers::PacketSwitchQuery; -pub type EventFn = Box, &T) + 'static + Send + Sync>; +pub type BoxedEventFn = Box, &T) + 'static + Send + Sync>; + +pub trait EventFn: + Fn(&mut PacketSwitchQuery<'_>, &T) + 'static + Send + Sync + Sized +{ + fn boxed(input: Self) -> BoxedEventFn { + Box::new(input) + } +} +impl EventFn for F where + F: Fn(&mut PacketSwitchQuery<'_>, &T) + 'static + Send + Sync +{ +} pub struct CommandCompletionRequest<'a> { pub query: &'a str, @@ -73,7 +85,7 @@ pub struct GlobalEventHandlers { } pub struct EventHandlers { - handlers: Vec>, + handlers: Vec>, } impl Default for EventHandlers {