-
-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
ace0cbf
commit a3b9e38
Showing
2 changed files
with
114 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
use std::collections::HashMap; | ||
|
||
use anyhow::Result; | ||
use rustc_hash::FxBuildHasher; | ||
use valence_protocol::{Decode, Packet, packets::play::ChatMessageC2s}; | ||
|
||
// We'll store the deserialization function separately from handlers | ||
type DeserializerFn = | ||
Box<dyn for<'a> Fn(&'a [u8]) -> Result<Box<dyn std::any::Any + Send + Sync + 'a>>>; | ||
type PacketHandler = Box<dyn Fn(&(dyn std::any::Any + Send + Sync)) -> Result<()>>; | ||
|
||
pub struct HandlerRegistry { | ||
// Store deserializer and multiple handlers separately | ||
deserializers: HashMap<i32, DeserializerFn, FxBuildHasher>, | ||
handlers: HashMap<i32, Vec<PacketHandler>, FxBuildHasher>, | ||
} | ||
|
||
impl HandlerRegistry { | ||
#[must_use] | ||
pub fn new() -> Self { | ||
Self { | ||
deserializers: HashMap::default(), | ||
handlers: HashMap::default(), | ||
} | ||
} | ||
|
||
// Register a packet type's deserializer | ||
pub fn register_packet<P>(&mut self) | ||
where | ||
P: Packet + Send + Sync + for<'a> Decode<'a>, | ||
{ | ||
let deserializer: DeserializerFn = Box::new( | ||
|mut bytes: &[u8]| -> Result<Box<dyn std::any::Any + Send + Sync>> { | ||
let bytes = &mut bytes; | ||
let packet = P::decode(bytes)?; | ||
Ok(Box::new(packet)) | ||
}, | ||
); | ||
|
||
self.deserializers.insert(P::ID, deserializer); | ||
// Initialize the handlers vector if it doesn't exist | ||
self.handlers.entry(P::ID).or_insert_with(Vec::new); | ||
} | ||
|
||
// Add a handler for a packet type | ||
pub fn add_handler<P>(&mut self, handler: impl for<'a> Fn(&'a P) -> Result<()> + Send + Sync) | ||
where | ||
P: Packet + Send + Sync + for<'a> Decode<'a>, | ||
{ | ||
// Ensure the packet type is registered | ||
if !self.deserializers.contains_key(&P::ID) { | ||
self.register_packet::<P>(); | ||
} | ||
|
||
// Wrap the typed handler to work with Any | ||
let boxed_handler: PacketHandler = Box::new(move |any_packet| { | ||
let packet = any_packet | ||
.downcast_ref::<P>() | ||
.ok_or_else(|| anyhow::anyhow!("Invalid packet type"))?; | ||
handler(packet) | ||
}); | ||
|
||
// Add the handler to the vector | ||
self.handlers.entry(P::ID).or_default().push(boxed_handler); | ||
} | ||
|
||
// Process a packet, calling all registered handlers | ||
pub fn process_packet(&self, id: i32, bytes: &[u8]) -> Result<()> { | ||
// Get the deserializer | ||
let deserializer = self | ||
.deserializers | ||
.get(&id) | ||
.ok_or_else(|| anyhow::anyhow!("No deserializer registered for packet ID: {}", id))?; | ||
|
||
// Deserialize the packet once | ||
let packet = deserializer(bytes)?; | ||
|
||
// Get all handlers for this packet type | ||
// let handlers = self | ||
// .handlers | ||
// .get(&id) | ||
// .ok_or_else(|| anyhow::anyhow!("No handlers registered for packet ID: {}", id))?; | ||
// | ||
// // Call all handlers with the deserialized packet | ||
// for handler in handlers { | ||
// handler(&*packet)?; | ||
// } | ||
|
||
Ok(()) | ||
} | ||
} | ||
|
||
fn main() -> Result<()> { | ||
let mut registry = HandlerRegistry::new(); | ||
|
||
// Register multiple handlers for ChatPacket | ||
registry.add_handler::<ChatMessageC2s<'_>>(|packet| { | ||
println!("Handler 1: {:?}", packet); | ||
Ok(()) | ||
}); | ||
|
||
Ok(()) | ||
} |