You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
427 lines
14 KiB
427 lines
14 KiB
8 months ago
|
using System;
|
||
|
using System.Collections.Generic;
|
||
|
using UnityEngine;
|
||
|
|
||
|
namespace AX.MessageSystem
|
||
|
{
|
||
|
/// <summary>
|
||
|
/// 消息分发中心。
|
||
|
/// </summary>
|
||
|
public static class MessageDispatcher
|
||
|
{
|
||
|
internal class Pair
|
||
|
{
|
||
|
public string MessageType;
|
||
|
public Action<IMessage> Handler;
|
||
|
|
||
|
public Pair() { }
|
||
|
public Pair(string messageType, Action<IMessage> handler)
|
||
|
{
|
||
|
MessageType = messageType;
|
||
|
Handler = handler;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal const float Immediate = 0.0f;
|
||
|
internal const float NextFrame = -1.0f;
|
||
|
|
||
|
private static Dictionary<string, List<Pair>> filteredHandlers = new Dictionary<string, List<Pair>>();
|
||
|
private static Dictionary<string, Action<IMessage>> messageHandlers = new Dictionary<string, Action<IMessage>>();
|
||
|
|
||
|
private static List<IMessage> messages = new List<IMessage>();
|
||
|
|
||
|
public static void Clear()
|
||
|
{
|
||
|
foreach (var pair in filteredHandlers)
|
||
|
pair.Value.Clear();
|
||
|
|
||
|
filteredHandlers.Clear();
|
||
|
messageHandlers.Clear();
|
||
|
|
||
|
messages.Clear();
|
||
|
}
|
||
|
|
||
|
public static void AddListener(string messageType, Action<IMessage> handler)
|
||
|
{
|
||
|
AddListener(messageType, handler, default(string));
|
||
|
}
|
||
|
|
||
|
public static void AddListener(string messageType, Action<IMessage> handler, string filter)
|
||
|
{
|
||
|
if (string.IsNullOrEmpty(messageType) || handler == null)
|
||
|
throw new ArgumentNullException("messageType or handler is not be null.");
|
||
|
|
||
|
if (string.IsNullOrEmpty(filter))
|
||
|
{
|
||
|
if (messageHandlers.ContainsKey(messageType))
|
||
|
messageHandlers[messageType] += handler;
|
||
|
else
|
||
|
messageHandlers[messageType] = handler;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
List<Pair> handlers = null;
|
||
|
|
||
|
if (filteredHandlers.TryGetValue(filter, out handlers))
|
||
|
{
|
||
|
var index = handlers.FindIndex((pair) => pair.MessageType == messageType);
|
||
|
|
||
|
if (index >= 0)
|
||
|
handlers[index].Handler += handler;
|
||
|
else
|
||
|
handlers.Add(new Pair(messageType, handler));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
var list = new List<Pair>();
|
||
|
|
||
|
list.Add(new Pair(messageType, handler));
|
||
|
filteredHandlers.Add(filter, list);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static void AddListener(string messageType, Action<IMessage> handler, params string[] filters)
|
||
|
{
|
||
|
if (string.IsNullOrEmpty(messageType) || handler == null)
|
||
|
throw new ArgumentNullException("messageType or handler is not be null.");
|
||
|
|
||
|
for (var i = 0; i < filters.Length; ++i)
|
||
|
{
|
||
|
var filter = filters[i];
|
||
|
|
||
|
if (string.IsNullOrEmpty(filter))
|
||
|
{
|
||
|
if (messageHandlers.ContainsKey(messageType))
|
||
|
messageHandlers[messageType] += handler;
|
||
|
else
|
||
|
messageHandlers[messageType] = handler;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
List<Pair> handlers = null;
|
||
|
|
||
|
if (filteredHandlers.TryGetValue(filter, out handlers))
|
||
|
{
|
||
|
var index = handlers.FindIndex((pair) => pair.MessageType == messageType);
|
||
|
|
||
|
if (index >= 0)
|
||
|
handlers[index].Handler += handler;
|
||
|
else
|
||
|
handlers.Add(new Pair(messageType, handler));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
var list = new List<Pair>();
|
||
|
|
||
|
list.Add(new Pair(messageType, handler));
|
||
|
filteredHandlers.Add(filter, list);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static void RemoveListener(string messageType, Action<IMessage> handler)
|
||
|
{
|
||
|
RemoveListener(messageType, handler, default(string));
|
||
|
}
|
||
|
|
||
|
public static void RemoveListener(string messageType, Action<IMessage> handler, string filter)
|
||
|
{
|
||
|
if (string.IsNullOrEmpty(messageType) || handler == null)
|
||
|
throw new ArgumentNullException("messageType or handler is not be null.");
|
||
|
|
||
|
if (string.IsNullOrEmpty(filter))
|
||
|
{
|
||
|
if (messageHandlers.ContainsKey(messageType))
|
||
|
{
|
||
|
messageHandlers[messageType] -= handler;
|
||
|
|
||
|
if (messageHandlers[messageType] == null)
|
||
|
messageHandlers.Remove(messageType);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
List<Pair> handlers = null;
|
||
|
|
||
|
if (filteredHandlers.TryGetValue(filter, out handlers))
|
||
|
{
|
||
|
var index = handlers.FindIndex((pair) => pair.MessageType == messageType);
|
||
|
|
||
|
if (index >= 0)
|
||
|
{
|
||
|
handlers[index].Handler -= handler;
|
||
|
|
||
|
if (handlers[index].Handler == null)
|
||
|
handlers.RemoveAt(index);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static void RemoveListener(string messageType, Action<IMessage> handler, params string[] filters)
|
||
|
{
|
||
|
if (string.IsNullOrEmpty(messageType) || handler == null)
|
||
|
throw new ArgumentNullException("messageType or handler is not be null.");
|
||
|
|
||
|
for (var i = 0; i < filters.Length; ++i)
|
||
|
{
|
||
|
var filter = filters[i];
|
||
|
|
||
|
if (string.IsNullOrEmpty(filter))
|
||
|
{
|
||
|
if (messageHandlers.ContainsKey(messageType))
|
||
|
{
|
||
|
messageHandlers[messageType] -= handler;
|
||
|
|
||
|
if (messageHandlers[messageType] == null)
|
||
|
messageHandlers.Remove(messageType);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
List<Pair> handlers = null;
|
||
|
|
||
|
if (filteredHandlers.TryGetValue(filter, out handlers))
|
||
|
{
|
||
|
var index = handlers.FindIndex((pair) => pair.MessageType == messageType);
|
||
|
|
||
|
if (index >= 0)
|
||
|
{
|
||
|
handlers[index].Handler -= handler;
|
||
|
|
||
|
if (handlers[index].Handler == null)
|
||
|
handlers.RemoveAt(index);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static void Update()
|
||
|
{
|
||
|
//处理延迟消息并决定何时发送它
|
||
|
for (int i = 0; i < messages.Count; i++)
|
||
|
{
|
||
|
var message = messages[i];
|
||
|
|
||
|
message.Delay -= Time.deltaTime;
|
||
|
|
||
|
if (message.Delay < 0)
|
||
|
message.Delay = Immediate;
|
||
|
|
||
|
//是时候发送消息了
|
||
|
if (!message.IsSent && message.Delay == Immediate)
|
||
|
SendMessage(message);
|
||
|
}
|
||
|
|
||
|
//回收发送的消息
|
||
|
for (int i = messages.Count - 1; i >= 0; i--)
|
||
|
{
|
||
|
var message = messages[i];
|
||
|
|
||
|
if (message.IsSent || message.IsHandled)
|
||
|
{
|
||
|
messages.RemoveAt(i);
|
||
|
|
||
|
Message.Release((Message)message);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static void SendMessage(IMessage message)
|
||
|
{
|
||
|
if (message == null || string.IsNullOrEmpty(message.Type))
|
||
|
throw new ArgumentNullException("message");
|
||
|
|
||
|
bool missing = true;
|
||
|
|
||
|
// 处理延迟消息
|
||
|
if (message.Delay > 0 || message.Delay < 0)
|
||
|
{
|
||
|
messages.Add(message);
|
||
|
|
||
|
missing = false;
|
||
|
}
|
||
|
else if (message.Filters == null)
|
||
|
{
|
||
|
Action<IMessage> action = null;
|
||
|
|
||
|
if (messageHandlers.TryGetValue(message.Type, out action))
|
||
|
{
|
||
|
//触发消息回调
|
||
|
message.IsSent = true;
|
||
|
action(message);
|
||
|
message.IsHandled = true;
|
||
|
|
||
|
missing = false;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for (var i = 0; i < message.Filters.Length; ++i)
|
||
|
{
|
||
|
var filter = message.Filters[i];
|
||
|
|
||
|
if (string.IsNullOrEmpty(filter))
|
||
|
{
|
||
|
Action<IMessage> action = null;
|
||
|
|
||
|
if (messageHandlers.TryGetValue(message.Type, out action))
|
||
|
{
|
||
|
message.IsSent = true;
|
||
|
action(message);
|
||
|
message.IsHandled = true;
|
||
|
|
||
|
missing = false;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
List<Pair> handlers = null;
|
||
|
|
||
|
if (filteredHandlers.TryGetValue(filter, out handlers))
|
||
|
{
|
||
|
var index = handlers.FindIndex((pair) => pair.MessageType == message.Type);
|
||
|
|
||
|
if (index >= 0)
|
||
|
{
|
||
|
message.IsSent = true;
|
||
|
handlers[index].Handler(message);
|
||
|
message.IsHandled = true;
|
||
|
|
||
|
missing = false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//如果没有对应的接收方
|
||
|
if (missing)
|
||
|
{
|
||
|
if (Application.isEditor)
|
||
|
Debug.LogError("[MessageSystem] 该消息类型 { " + message.Type + " } 没有对应的接收方处理。");
|
||
|
|
||
|
message.IsSent = true;
|
||
|
message.IsHandled = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static void SendMessage(string type)
|
||
|
{
|
||
|
SendMessage(null, type, default(object), Immediate, default(string));
|
||
|
}
|
||
|
|
||
|
// 注释掉下面方法的原因是开发人员经常使用发送数据的方法
|
||
|
// 但编译器会定位方法重载到这里
|
||
|
// 这导致了非必要的排错
|
||
|
// 如果想要延迟发送,请使用下面更精确的重载方法
|
||
|
//public static void SendMessage(string type, string filter)
|
||
|
//{
|
||
|
// SendMessage(null, type, default(object), Immediate, filter);
|
||
|
//}
|
||
|
|
||
|
// public static void SendMessage(string type, float delay)
|
||
|
// {
|
||
|
// SendMessage(null, type, default(object), delay, default(string));
|
||
|
// }
|
||
|
|
||
|
// public static void SendMessage(string type, float delay, string filter)
|
||
|
// {
|
||
|
// SendMessage(null, type, default(object), delay, filter);
|
||
|
// }
|
||
|
|
||
|
public static void SendMessage(string type, object data)
|
||
|
{
|
||
|
SendMessage(null, type, data, Immediate, default(string));
|
||
|
}
|
||
|
|
||
|
public static void SendMessage(string type, object data, string filter)
|
||
|
{
|
||
|
SendMessage(null, type, data, Immediate, filter);
|
||
|
}
|
||
|
|
||
|
public static void SendMessage(string type, object data, float delay)
|
||
|
{
|
||
|
SendMessage(null, type, data, delay, default(string));
|
||
|
}
|
||
|
|
||
|
public static void SendMessage(string type, object data, float delay, string filter)
|
||
|
{
|
||
|
SendMessage(null, type, data, delay, filter);
|
||
|
}
|
||
|
|
||
|
public static void SendMessage(object sender, string type)
|
||
|
{
|
||
|
SendMessage(sender, type, default(object), Immediate, default(string));
|
||
|
}
|
||
|
|
||
|
//public static void SendMessage(object sender, string type, float delay)
|
||
|
//{
|
||
|
// SendMessage(sender, type, default(object), delay, default(string));
|
||
|
//}
|
||
|
|
||
|
public static void SendMessage(object sender, string type, string filter)
|
||
|
{
|
||
|
SendMessage(sender, type, default(object), Immediate, filter);
|
||
|
}
|
||
|
|
||
|
public static void SendMessage(object sender, string type, float delay, string filter)
|
||
|
{
|
||
|
SendMessage(sender, type, default(object), delay, filter);
|
||
|
}
|
||
|
|
||
|
public static void SendMessage(object sender, string type, object data)
|
||
|
{
|
||
|
SendMessage(sender, type, data, Immediate, default(string));
|
||
|
}
|
||
|
|
||
|
public static void SendMessage(object sender, string type, object data, float delay)
|
||
|
{
|
||
|
SendMessage(sender, type, data, delay, default(string));
|
||
|
}
|
||
|
|
||
|
public static void SendMessage(object sender, string type, object data, string filter)
|
||
|
{
|
||
|
SendMessage(sender, type, data, Immediate, filter);
|
||
|
}
|
||
|
|
||
|
public static void SendMessage(object sender, string type, object data, float delay, string filter)
|
||
|
{
|
||
|
var message = Message.Acquire();
|
||
|
|
||
|
message.Sender = sender;
|
||
|
message.Type = type;
|
||
|
message.Data = data;
|
||
|
message.Delay = delay;
|
||
|
|
||
|
if (!string.IsNullOrEmpty(filter))
|
||
|
message.Filters = new string[] { filter };
|
||
|
|
||
|
SendMessage(message);
|
||
|
|
||
|
if (delay == Immediate)
|
||
|
Message.Release(message);
|
||
|
}
|
||
|
|
||
|
public static void SendMessage(object sender, string type, object data, float delay, params string[] filters)
|
||
|
{
|
||
|
var message = Message.Acquire();
|
||
|
|
||
|
message.Sender = sender;
|
||
|
message.Type = type;
|
||
|
message.Data = data;
|
||
|
message.Delay = delay;
|
||
|
|
||
|
if (filters != null)
|
||
|
message.Filters = filters;
|
||
|
|
||
|
SendMessage(message);
|
||
|
|
||
|
if (delay == Immediate)
|
||
|
Message.Release(message);
|
||
|
}
|
||
|
}
|
||
|
}
|