@@ -10,17 +10,17 @@ use bevy_ecs::{
1010 lifecycle:: RemovedComponentEntity ,
1111 message:: MessageCursor ,
1212 query:: QueryBuilder ,
13- reflect:: { AppTypeRegistry , ReflectComponent , ReflectResource } ,
13+ reflect:: { AppTypeRegistry , ReflectComponent , ReflectEvent , ReflectResource } ,
1414 system:: { In , Local } ,
15- world:: { EntityRef , EntityWorldMut , FilteredEntityRef , World } ,
15+ world:: { EntityRef , EntityWorldMut , FilteredEntityRef , Mut , World } ,
1616} ;
1717use bevy_log:: warn_once;
1818use bevy_platform:: collections:: HashMap ;
1919use bevy_reflect:: {
2020 serde:: { ReflectSerializer , TypedReflectDeserializer } ,
21- GetPath , PartialReflect , TypeRegistration , TypeRegistry ,
21+ DynamicStruct , GetPath , PartialReflect , TypeRegistration , TypeRegistry ,
2222} ;
23- use serde:: { de:: DeserializeSeed as _, Deserialize , Serialize } ;
23+ use serde:: { de:: DeserializeSeed as _, de :: IntoDeserializer , Deserialize , Serialize } ;
2424use serde_json:: { Map , Value } ;
2525
2626use crate :: {
@@ -83,6 +83,9 @@ pub const BRP_MUTATE_RESOURCE_METHOD: &str = "world.mutate_resources";
8383/// The method path for a `world.list_resources` request.
8484pub const BRP_LIST_RESOURCES_METHOD : & str = "world.list_resources" ;
8585
86+ /// The method path for a `world.trigger_event` request.
87+ pub const BRP_TRIGGER_EVENT_METHOD : & str = "world.trigger_event" ;
88+
8689/// The method path for a `registry.schema` request.
8790pub const BRP_REGISTRY_SCHEMA_METHOD : & str = "registry.schema" ;
8891
@@ -299,6 +302,19 @@ pub struct BrpMutateResourcesParams {
299302 pub value : Value ,
300303}
301304
305+ /// `world.trigger_event`:
306+ ///
307+ /// The server responds with a null.
308+ #[ derive( Debug , Serialize , Deserialize , Clone , PartialEq ) ]
309+ struct BrpTriggerEventParams {
310+ /// The [full path] of the event to trigger.
311+ ///
312+ /// [full path]: bevy_reflect::TypePath::type_path
313+ pub event : String ,
314+ /// The serialized value of the event to be triggered, if any.
315+ pub value : Option < Value > ,
316+ }
317+
302318/// Describes the data that is to be fetched in a query.
303319#[ derive( Debug , Serialize , Deserialize , Clone , Default , PartialEq ) ]
304320pub struct BrpQuery {
@@ -1348,6 +1364,44 @@ pub fn process_remote_list_components_watching_request(
13481364 }
13491365}
13501366
1367+ /// Handles a `world.trigger_event` request coming from a client.
1368+ pub fn process_remote_trigger_event_request (
1369+ In ( params) : In < Option < Value > > ,
1370+ world : & mut World ,
1371+ ) -> BrpResult {
1372+ let BrpTriggerEventParams { event, value } = parse_some ( params) ?;
1373+
1374+ world. resource_scope ( |world, registry : Mut < AppTypeRegistry > | {
1375+ let registry = registry. read ( ) ;
1376+
1377+ let Some ( registration) = registry. get_with_type_path ( & event) else {
1378+ return Err ( BrpError :: resource_error ( format ! (
1379+ "Unknown event type: `{event}`"
1380+ ) ) ) ;
1381+ } ;
1382+ let Some ( reflect_event) = registration. data :: < ReflectEvent > ( ) else {
1383+ return Err ( BrpError :: resource_error ( format ! (
1384+ "Event `{event}` is not reflectable"
1385+ ) ) ) ;
1386+ } ;
1387+
1388+ if let Some ( payload) = value {
1389+ let payload: Box < dyn PartialReflect > =
1390+ TypedReflectDeserializer :: new ( registration, & registry)
1391+ . deserialize ( payload. into_deserializer ( ) )
1392+ . map_err ( |err| {
1393+ BrpError :: resource_error ( format ! ( "{event} is invalid: {err}" ) )
1394+ } ) ?;
1395+ reflect_event. trigger ( world, & * payload, & registry) ;
1396+ } else {
1397+ let payload = DynamicStruct :: default ( ) ;
1398+ reflect_event. trigger ( world, & payload, & registry) ;
1399+ }
1400+
1401+ Ok ( Value :: Null )
1402+ } )
1403+ }
1404+
13511405/// Handles a `registry.schema` request (list all registry types in form of schema) coming from a client.
13521406pub fn export_registry_types ( In ( params) : In < Option < Value > > , world : & World ) -> BrpResult {
13531407 let filter: BrpJsonSchemaQueryFilter = match params {
@@ -1628,6 +1682,11 @@ mod tests {
16281682 }
16291683
16301684 use super :: * ;
1685+ use bevy_ecs:: {
1686+ component:: Component , event:: Event , observer:: On , resource:: Resource , system:: ResMut ,
1687+ } ;
1688+ use bevy_reflect:: Reflect ;
1689+ use serde_json:: Value :: Null ;
16311690
16321691 #[ test]
16331692 fn insert_reflect_only_component ( ) {
@@ -1659,6 +1718,37 @@ mod tests {
16591718 insert_reflected_components ( e, deserialized_components) . expect ( "FAIL" ) ;
16601719 }
16611720
1721+ #[ test]
1722+ fn trigger_reflect_only_event ( ) {
1723+ #[ derive( Event , Reflect ) ]
1724+ #[ reflect( Event ) ]
1725+ struct Pass ;
1726+
1727+ #[ derive( Resource ) ]
1728+ struct TestResult ( pub bool ) ;
1729+
1730+ let atr = AppTypeRegistry :: default ( ) ;
1731+ {
1732+ let mut register = atr. write ( ) ;
1733+ register. register :: < Pass > ( ) ;
1734+ }
1735+ let mut world = World :: new ( ) ;
1736+ world. add_observer ( move |_event : On < Pass > , mut result : ResMut < TestResult > | result. 0 = true ) ;
1737+ world. insert_resource ( TestResult ( false ) ) ;
1738+ world. insert_resource ( atr) ;
1739+
1740+ let params = serde_json:: to_value ( & BrpTriggerEventParams {
1741+ event : "bevy_remote::builtin_methods::tests::Pass" . to_owned ( ) ,
1742+ value : None ,
1743+ } )
1744+ . expect ( "FAIL" ) ;
1745+ assert_eq ! (
1746+ process_remote_trigger_event_request( In ( Some ( params) ) , & mut world) ,
1747+ Ok ( Null )
1748+ ) ;
1749+ assert ! ( world. resource:: <TestResult >( ) . 0 ) ;
1750+ }
1751+
16621752 #[ test]
16631753 fn serialization_tests ( ) {
16641754 test_serialize_deserialize ( BrpQueryRow {
0 commit comments