From 5fee3f5ab1e42df49a6d8ba2c7f10fae0a7aba2e Mon Sep 17 00:00:00 2001 From: Julien Lemaire Date: Fri, 8 Jul 2022 23:39:33 +0200 Subject: [PATCH] Several callbacks can be added to a same message type and disposed (#197) --- .../Runtime/Scripts/Room/ColyseusRoom.cs | 81 +++++++++++++------ 1 file changed, 56 insertions(+), 25 deletions(-) diff --git a/Assets/Colyseus/Runtime/Scripts/Room/ColyseusRoom.cs b/Assets/Colyseus/Runtime/Scripts/Room/ColyseusRoom.cs index 2aae26d8..6601a7c8 100644 --- a/Assets/Colyseus/Runtime/Scripts/Room/ColyseusRoom.cs +++ b/Assets/Colyseus/Runtime/Scripts/Room/ColyseusRoom.cs @@ -282,18 +282,53 @@ public async Task Send(string type, object message) await colyseusConnection.Send(bytes); } + /// + /// Disposable class to return with OnMessage function, so that a message callback can be removed. + /// + /// The type of object the message responds with + private class MessageRemover : IDisposable + { + private string _type; + private Action _targetHandler; + private Dictionary _onMessageHandlers; + + public MessageRemover(string type, + Action targetHandler, + Dictionary onMessageHandlers) + { + _type = type; + _targetHandler = targetHandler; + _onMessageHandlers = onMessageHandlers; + } + + public void Dispose() + { + var messageHandler = _onMessageHandlers[_type] as ColyseusMessageHandler; + messageHandler.Action -= _targetHandler; + if (messageHandler.Action == null) { + _onMessageHandlers.Remove(_type); + } + } + } + /// /// Method to add new message handlers to the room /// /// The type of message received /// /// The type of object this message should respond with - public void OnMessage(string type, Action handler) + /// IDisposable object to remove the message handler when called + public IDisposable OnMessage(string type, Action handler) { - OnMessageHandlers.Add(type, new ColyseusMessageHandler - { - Action = handler - }); + if (OnMessageHandlers.ContainsKey(type)) { + (OnMessageHandlers[type] as ColyseusMessageHandler).Action += handler; + } else { + OnMessageHandlers.Add(type, new ColyseusMessageHandler + { + Action = handler + }); + } + return new MessageRemover(type, handler, OnMessageHandlers); } /// @@ -302,12 +337,10 @@ public void OnMessage(string type, Action handler) /// The type of message received /// /// The type of object this message should respond with - public void OnMessage(byte type, Action handler) + /// IDisposable object to remove the message handler when called + public IDisposable OnMessage(byte type, Action handler) { - OnMessageHandlers.Add("i" + type, new ColyseusMessageHandler - { - Action = handler - }); + return this.OnMessage("i" + type, handler); } /// @@ -315,12 +348,10 @@ public void OnMessage(byte type, Action handler) /// /// /// The type of object this message should respond with - public void OnMessage(Action handler) where MessageType : Schema.Schema, new() + /// IDisposable object to remove the message handler when called + public IDisposable OnMessage(Action handler) where MessageType : Schema.Schema, new() { - OnMessageHandlers.Add("s" + typeof(MessageType), new ColyseusMessageHandler - { - Action = handler - }); + return this.OnMessage("s" + typeof(MessageType), handler); } /// @@ -372,15 +403,15 @@ protected async void ParseMessage(byte[] bytes) if (bytes.Length > offset) { - try { - serializer.Handshake(bytes, offset); - } - catch (Exception e) - { - await Leave(false); - OnError?.Invoke(ColyseusErrorCode.SCHEMA_MISMATCH, e.Message); - return; - } + try { + serializer.Handshake(bytes, offset); + } + catch (Exception e) + { + await Leave(false); + OnError?.Invoke(ColyseusErrorCode.SCHEMA_MISMATCH, e.Message); + return; + } } OnJoin?.Invoke(); @@ -423,7 +454,7 @@ protected async void ParseMessage(byte[] bytes) } else if (code == ColyseusProtocol.ROOM_STATE) { - SetState(bytes, 1); + SetState(bytes, 1); } else if (code == ColyseusProtocol.ROOM_STATE_PATCH) {