using System;
using System.Collections.Generic;
using UnityEngine;
namespace Mirror
{
///
/// Component that controls visibility of networked objects based on match id.
/// Any object with this component on it will only be visible to other objects in the same match.
/// This would be used to isolate players to their respective matches within a single game server instance.
///
[DisallowMultipleComponent]
[AddComponentMenu("Network/NetworkMatchChecker")]
[RequireComponent(typeof(NetworkIdentity))]
[HelpURL("https://mirror-networking.com/docs/Components/NetworkMatchChecker.html")]
public class NetworkMatchChecker : NetworkVisibility
{
static readonly Dictionary> matchPlayers = new Dictionary>();
Guid currentMatch = Guid.Empty;
[Header("Diagnostics")]
[SyncVar]
public string currentMatchDebug;
///
/// Set this to the same value on all networked objects that belong to a given match
///
public Guid matchId
{
get { return currentMatch; }
set
{
if (currentMatch == value) return;
// cache previous match so observers in that match can be rebuilt
Guid previousMatch = currentMatch;
// Set this to the new match this object just entered ...
currentMatch = value;
// ... and copy the string for the inspector because Unity can't show Guid directly
currentMatchDebug = currentMatch.ToString();
if (previousMatch != Guid.Empty)
{
// Remove this object from the hashset of the match it just left
matchPlayers[previousMatch].Remove(netIdentity);
// RebuildObservers of all NetworkIdentity's in the match this object just left
RebuildMatchObservers(previousMatch);
}
if (currentMatch != Guid.Empty)
{
// Make sure this new match is in the dictionary
if (!matchPlayers.ContainsKey(currentMatch))
matchPlayers.Add(currentMatch, new HashSet());
// Add this object to the hashset of the new match
matchPlayers[currentMatch].Add(netIdentity);
// RebuildObservers of all NetworkIdentity's in the match this object just entered
RebuildMatchObservers(currentMatch);
}
else
{
// Not in any match now...RebuildObservers will clear and add self
netIdentity.RebuildObservers(false);
}
}
}
public override void OnStartServer()
{
if (currentMatch == Guid.Empty) return;
if (!matchPlayers.ContainsKey(currentMatch))
matchPlayers.Add(currentMatch, new HashSet());
matchPlayers[currentMatch].Add(netIdentity);
// No need to rebuild anything here.
// identity.RebuildObservers is called right after this from NetworkServer.SpawnObject
}
void RebuildMatchObservers(Guid specificMatch)
{
foreach (NetworkIdentity networkIdentity in matchPlayers[specificMatch])
if (networkIdentity != null)
networkIdentity.RebuildObservers(false);
}
#region Observers
///
/// Callback used by the visibility system to determine if an observer (player) can see this object.
/// If this function returns true, the network connection will be added as an observer.
///
/// Network connection of a player.
/// True if the player can see this object.
public override bool OnCheckObserver(NetworkConnection conn)
{
// Not Visible if not in a match
if (matchId == Guid.Empty)
return false;
NetworkMatchChecker networkMatchChecker = conn.identity.GetComponent();
if (networkMatchChecker == null)
return false;
return networkMatchChecker.matchId == matchId;
}
///
/// Callback used by the visibility system to (re)construct the set of observers that can see this object.
/// Implementations of this callback should add network connections of players that can see this object to the observers set.
///
/// The new set of observers for this object.
/// True if the set of observers is being built for the first time.
public override void OnRebuildObservers(HashSet observers, bool initialize)
{
if (currentMatch == Guid.Empty) return;
foreach (NetworkIdentity networkIdentity in matchPlayers[currentMatch])
if (networkIdentity != null && networkIdentity.connectionToClient != null)
observers.Add(networkIdentity.connectionToClient);
}
#endregion
}
}