MatchInterestManagement.cs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. namespace Mirror
  5. {
  6. [AddComponentMenu("Network/ Interest Management/ Match/Match Interest Management")]
  7. public class MatchInterestManagement : InterestManagement
  8. {
  9. readonly Dictionary<Guid, HashSet<NetworkIdentity>> matchObjects =
  10. new Dictionary<Guid, HashSet<NetworkIdentity>>();
  11. readonly Dictionary<NetworkIdentity, Guid> lastObjectMatch =
  12. new Dictionary<NetworkIdentity, Guid>();
  13. readonly HashSet<Guid> dirtyMatches = new HashSet<Guid>();
  14. public override void OnSpawned(NetworkIdentity identity)
  15. {
  16. if (!identity.TryGetComponent<NetworkMatch>(out NetworkMatch networkMatch))
  17. return;
  18. Guid currentMatch = networkMatch.matchId;
  19. lastObjectMatch[identity] = currentMatch;
  20. // Guid.Empty is never a valid matchId...do not add to matchObjects collection
  21. if (currentMatch == Guid.Empty)
  22. return;
  23. // Debug.Log($"MatchInterestManagement.OnSpawned({identity.name}) currentMatch: {currentMatch}");
  24. if (!matchObjects.TryGetValue(currentMatch, out HashSet<NetworkIdentity> objects))
  25. {
  26. objects = new HashSet<NetworkIdentity>();
  27. matchObjects.Add(currentMatch, objects);
  28. }
  29. objects.Add(identity);
  30. }
  31. public override void OnDestroyed(NetworkIdentity identity)
  32. {
  33. lastObjectMatch.TryGetValue(identity, out Guid currentMatch);
  34. lastObjectMatch.Remove(identity);
  35. if (currentMatch != Guid.Empty && matchObjects.TryGetValue(currentMatch, out HashSet<NetworkIdentity> objects) && objects.Remove(identity))
  36. RebuildMatchObservers(currentMatch);
  37. }
  38. // internal so we can update from tests
  39. [ServerCallback]
  40. internal void Update()
  41. {
  42. // for each spawned:
  43. // if match changed:
  44. // add previous to dirty
  45. // add new to dirty
  46. foreach (NetworkIdentity netIdentity in NetworkServer.spawned.Values)
  47. {
  48. // Ignore objects that don't have a NetworkMatch component
  49. if (!netIdentity.TryGetComponent<NetworkMatch>(out NetworkMatch networkMatch))
  50. continue;
  51. Guid newMatch = networkMatch.matchId;
  52. lastObjectMatch.TryGetValue(netIdentity, out Guid currentMatch);
  53. // Guid.Empty is never a valid matchId
  54. // Nothing to do if matchId hasn't changed
  55. if (newMatch == Guid.Empty || newMatch == currentMatch)
  56. continue;
  57. // Mark new/old matches as dirty so they get rebuilt
  58. UpdateDirtyMatches(newMatch, currentMatch);
  59. // This object is in a new match so observers in the prior match
  60. // and the new match need to rebuild their respective observers lists.
  61. UpdateMatchObjects(netIdentity, newMatch, currentMatch);
  62. }
  63. // rebuild all dirty matches
  64. foreach (Guid dirtyMatch in dirtyMatches)
  65. RebuildMatchObservers(dirtyMatch);
  66. dirtyMatches.Clear();
  67. }
  68. void UpdateDirtyMatches(Guid newMatch, Guid currentMatch)
  69. {
  70. // Guid.Empty is never a valid matchId
  71. if (currentMatch != Guid.Empty)
  72. dirtyMatches.Add(currentMatch);
  73. dirtyMatches.Add(newMatch);
  74. }
  75. void UpdateMatchObjects(NetworkIdentity netIdentity, Guid newMatch, Guid currentMatch)
  76. {
  77. // Remove this object from the hashset of the match it just left
  78. // Guid.Empty is never a valid matchId
  79. if (currentMatch != Guid.Empty)
  80. matchObjects[currentMatch].Remove(netIdentity);
  81. // Set this to the new match this object just entered
  82. lastObjectMatch[netIdentity] = newMatch;
  83. // Make sure this new match is in the dictionary
  84. if (!matchObjects.ContainsKey(newMatch))
  85. matchObjects.Add(newMatch, new HashSet<NetworkIdentity>());
  86. // Add this object to the hashset of the new match
  87. matchObjects[newMatch].Add(netIdentity);
  88. }
  89. void RebuildMatchObservers(Guid matchId)
  90. {
  91. foreach (NetworkIdentity netIdentity in matchObjects[matchId])
  92. if (netIdentity != null)
  93. NetworkServer.RebuildObservers(netIdentity, false);
  94. }
  95. public override bool OnCheckObserver(NetworkIdentity identity, NetworkConnectionToClient newObserver)
  96. {
  97. // Never observed if no NetworkMatch component
  98. if (!identity.TryGetComponent<NetworkMatch>(out NetworkMatch identityNetworkMatch))
  99. return false;
  100. // Guid.Empty is never a valid matchId
  101. if (identityNetworkMatch.matchId == Guid.Empty)
  102. return false;
  103. // Never observed if no NetworkMatch component
  104. if (!newObserver.identity.TryGetComponent<NetworkMatch>(out NetworkMatch newObserverNetworkMatch))
  105. return false;
  106. // Guid.Empty is never a valid matchId
  107. if (newObserverNetworkMatch.matchId == Guid.Empty)
  108. return false;
  109. return identityNetworkMatch.matchId == newObserverNetworkMatch.matchId;
  110. }
  111. public override void OnRebuildObservers(NetworkIdentity identity, HashSet<NetworkConnectionToClient> newObservers)
  112. {
  113. if (!identity.TryGetComponent<NetworkMatch>(out NetworkMatch networkMatch))
  114. return;
  115. Guid matchId = networkMatch.matchId;
  116. // Guid.Empty is never a valid matchId
  117. if (matchId == Guid.Empty)
  118. return;
  119. if (!matchObjects.TryGetValue(matchId, out HashSet<NetworkIdentity> objects))
  120. return;
  121. // Add everything in the hashset for this object's current match
  122. foreach (NetworkIdentity networkIdentity in objects)
  123. if (networkIdentity != null && networkIdentity.connectionToClient != null)
  124. newObservers.Add(networkIdentity.connectionToClient);
  125. }
  126. }
  127. }