using System.Collections.Generic;
using UnityEngine;
using Stopwatch = System.Diagnostics.Stopwatch;
namespace LobbyRelaySample
{
///
/// Core mechanism for routing messages to arbitrary listeners.
/// This allows components with unrelated responsibilities to interact without becoming coupled, since message senders don't
/// need to know what (if anything) is receiving their messages.
///
public class Messenger : IMessenger
{
private List m_receivers = new List();
private const float k_durationToleranceMs = 10;
///
/// Assume that you won't receive messages in a specific order.
///
public virtual void Subscribe(IReceiveMessages receiver)
{
if (!m_receivers.Contains(receiver))
m_receivers.Add(receiver);
}
public virtual void Unsubscribe(IReceiveMessages receiver)
{
m_receivers.Remove(receiver);
}
///
/// Send a message to any subscribers, who will decide how to handle the message.
///
/// If there's some data relevant to the recipient, include it here.
public virtual void OnReceiveMessage(MessageType type, object msg)
{
Stopwatch stopwatch = new Stopwatch();
for (int r = 0; r < m_receivers.Count; r++)
{
stopwatch.Restart();
m_receivers[r].OnReceiveMessage(type, msg);
stopwatch.Stop();
if (stopwatch.ElapsedMilliseconds > k_durationToleranceMs)
Debug.LogWarning($"Message recipient \"{m_receivers[r]}\" took too long to process message \"{msg}\" of type {type}");
}
}
public void OnReProvided(IMessenger previousProvider)
{
if (previousProvider is Messenger)
m_receivers.AddRange((previousProvider as Messenger).m_receivers);
}
}
///
/// Ensure that message contents are obvious but not dependent on spelling strings correctly.
///
public enum MessageType
{
// These are assigned arbitrary explicit values so that if a MessageType is serialized and more enum values are later inserted/removed, the serialized values need not be reassigned.
// (If you want to remove a message, make sure it isn't serialized somewhere first.)
None = 0,
RenameRequest = 1,
JoinLobbyRequest = 2,
CreateLobbyRequest = 3,
QueryLobbies = 4,
ChangeGameState = 5,
LobbyUserStatus = 6,
UserSetEmote = 7,
EndGame = 8,
StartCountdown = 9,
CancelCountdown = 10,
ConfirmInGameState = 11,
DisplayErrorPopup = 12,
SetPlayerSound = 13,
QuickJoin = 14
}
///
/// Something that wants to subscribe to messages from arbitrary, unknown senders.
///
public interface IReceiveMessages
{
void OnReceiveMessage(MessageType type, object msg);
}
///
/// Something to which IReceiveMessages can send/subscribe for arbitrary messages.
///
public interface IMessenger : IReceiveMessages, IProvidable
{
void Subscribe(IReceiveMessages receiver);
void Unsubscribe(IReceiveMessages receiver);
}
}