Use single event system for client events
Fix #245
I think we probably should make the API nicer by using two functions. First function will read the resource from the registry by ID (like you tried to do before, like Bevy does for updates), iterates over all events and passes each event into a second function with the correct type. And let user to override only the second function. The same for both sending and receiving.
I suspect that ClientEventFns will be the same as the upcoming ServerEventFns. So I would move it upper to the network_event module and rename into NetworkEventFns.
Also instead of passing the world, we probably should pass a context struct like we do for components. This context will contain the current tick and TypeRegistry.
I think we probably should make the API nicer by using two functions. First function will read the resource from the registry by ID (like you tried to do before, like Bevy does for updates), iterates over all events and passes each event into a second function with the correct type. And let user to override only the second function. The same for both sending and receiving.
I'm not sure I fully understand, but doing that we need to store the ComponentId (maybe a few times), which seems unnecessary for the internal API. I suppose app can have maximum few hundred events, does this matter?
I suspect that
ClientEventFnswill be the same as the upcomingServerEventFns. So I would move it upper to thenetwork_eventmodule and rename intoNetworkEventFns.
The ServerEventFns have an additional pop_from_queue fn, so this is not applicable.
Also instead of passing the world, we probably should pass a context struct like we do for components. This context will contain the current tick and
TypeRegistry.
I'm not get this, can you elaborate more?
I'm not sure I fully understand, but doing that we need to store the ComponentId
I think that you can store it in the struct with functions. The idea behind it is to provide a nice API for users. Functions customization needed only to provide serialization/deserialization for events that doesn't have Serialize / Deserialize. For example, events with Box<dyn Reflect> inside.
The ServerEventFns have an additional pop_from_queue fn
Maybe we can unite pop_from_queue and receive? I think it will be possible with the mentioned two-functions approach.
I'm not get this, can you elaborate more?
Sure! Right now we pass &mut World into a single function. But let's consider separation into two functions for sending from server:
- Accepts
&mut World,EventContext, current tick and channel ID. ObtainsEvents<T>from it, iterates over all, passes eachTinto second serialize function and sends the returned bytes over a channel ID toRepliconServer. - Accepts
T,EventContext, serializes, returns bytes. Similar for sending and client functions. HereEventContextis a struct with necessary context for serialization. I would storeTypeRegistryand the current tick there. Take a look at functions for components API, it's similar. So the idea is to give user access only to necessary logic for serialization/deserialization instead of direct&mut World(maybe for sending we could use even only&World!). And instead of passingTypeRegistryand current tick directly, we also create a "context" struct with parameters. For consistency with components API and to avoid making breaking changes if we will need a new to pass more "context" data into functions.
Superseded by #262.