diff --git a/src/magicnet/core/network_manager.py b/src/magicnet/core/network_manager.py index 08fce30..0f61ae4 100644 --- a/src/magicnet/core/network_manager.py +++ b/src/magicnet/core/network_manager.py @@ -76,6 +76,12 @@ class NetworkManager(MessengerNode, Generic[AnyNetObject]): debug_mode: bool = False + current_message: NetMessage | None = dataclasses.field(default=None, init=False) + + @property + def current_sender(self) -> ConnectionHandle | None: + return self.current_message.sent_from if self.current_message else None + @property def managed_objects(self) -> dict[int, AnyNetObject]: return self.object_manager.managed_objects @@ -124,12 +130,14 @@ def process_datagram(self, messages: Iterable[NetMessage]): if self.debug_mode: self.emit(StandardEvents.DEBUG, f"Received message: {msg}") + self.current_message = msg try: self.dg_processor.process_message(msg) except Exception as e: # noqa: BLE001 self.emit( StandardEvents.EXCEPTION, "Error while processing a message", e ) + self.current_message = None def open_server(self, **kwargs): """ diff --git a/src/magicnet/netobjects/network_object.py b/src/magicnet/netobjects/network_object.py index 9e891fc..3590e88 100644 --- a/src/magicnet/netobjects/network_object.py +++ b/src/magicnet/netobjects/network_object.py @@ -261,13 +261,19 @@ def resolve_field(self, message: str) -> tuple[int, int]: raise errors.UnknownObjectMessage(self.network_name, message) return self.message_index[message] - def send_message(self, message: str, args: list | tuple = ()) -> None: + def send_message( + self, + message: str, + args: list | tuple = (), + *, + receiver: ConnectionHandle | None = None, + ) -> None: args = unpack_dataclasses(args) role_id, field_id = self.resolve_field(message) self.persist_field_data(role_id, field_id, list(args)) if self.object_state == ObjectState.GENERATED: self.manager.object_manager.request_call_field( - self, role_id, field_id, args + receiver, self, role_id, field_id, args ) @abc.abstractmethod diff --git a/src/magicnet/netobjects/network_object_manager.py b/src/magicnet/netobjects/network_object_manager.py index 260e313..3feefe4 100644 --- a/src/magicnet/netobjects/network_object_manager.py +++ b/src/magicnet/netobjects/network_object_manager.py @@ -152,10 +152,19 @@ def create_remote_object(self, obj: NetworkObject, owner: int = 0): ) self.manager.send_message(msg) - def request_call_field(self, obj: NetworkObject, role: int, field: int, params): + def request_call_field( + self, + receiver: ConnectionHandle | None, + obj: NetworkObject, + role: int, + field: int, + params, + ): msg = NetMessage( StandardMessageTypes.SET_OBJECT_FIELD, (obj.oid, role, field, params) ) + if receiver is not None: + msg.destination = receiver self.manager.send_message(msg) def request_visible_objects(self): diff --git a/tests/net_objects/test_net_fields.py b/tests/net_objects/test_net_fields.py index 3cfafd0..19906e1 100644 --- a/tests/net_objects/test_net_fields.py +++ b/tests/net_objects/test_net_fields.py @@ -153,3 +153,42 @@ def net_delete(self) -> None: cl_object = client.managed_objects.get(srv_object.oid) assert cl_object.a == 0 assert cl_object.b == 100 + + +def test_message_receiver(): + @dataclasses.dataclass + class TestNetObject(NetworkObject): + network_name = "test_obj" + object_role = 0 + + value: int = 0 + + @NetworkField + def set_value(self, value: network_types.uint16 = 256): + self.value = value + + @NetworkField + def set_my_value(self, val: network_types.uint16 = 256): + self.send_message("set_value", [val], receiver=self.manager.current_sender) + + def net_create(self) -> None: + pass + + def net_delete(self) -> None: + pass + + tester = FlexibleNetworkObjectTester.create_and_start(TestNetObject, TestNetObject) + c1 = tester.make_client() + c2 = tester.make_client() + + srv_object = TestNetObject(tester.server) + srv_object.send_message("set_value", [100]) + srv_object.request_generate() + + c1_object = c1.managed_objects[srv_object.oid] + c2_object = c2.managed_objects[srv_object.oid] + assert c1_object.value == c2_object.value == 100 + + c2_object.send_message("set_my_value", [200]) + assert c2_object.value == 200 + assert c1_object.value == 100