MatchInterestManagement.cs 5.8 KB

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