private void DebugState() { // skip update if debug text is off if (!DebugLogText.gameObject.activeInHierarchy) { return; } if ((debugStateCooldown -= Time.deltaTime) > 0) { return; } debugStateCooldown = 1f; string s = $"{System.DateTime.Now} localPid={Networking.LocalPlayer.playerId} master?={Networking.IsMaster} initCheck={lastInitializeCheck}\n" + $"broadcast={broadcastCooldown} releaseAttempt={releaseOwnershipAttemptCooldown} takeAttempt={takeOwnershipAttemptCooldown}\n" + $"localPlayerState={(localPlayerState == null ? "null" : localPlayerState.gameObject.name)}\n"; for (int i = 0; i < playerStates.Length; i++) { if ((i % 4) == 0) { s += "\n"; } MatchingTrackerPlayerState playerState = playerStates[i]; var o = playerState.GetExplicitOwner(); var sinceDeser = Time.time - playerState.lastDeserialization; s += $"[{i}]=[{(o == null ? "" : GetDisplayName(o))}]:{playerState.ownerId}:{sinceDeser:00.} "; } s += $"\nlocalPop={localStatePopulation} localPlayerid={Networking.LocalPlayer.playerId}"; DebugStateText.text = s; DisplayFullState(); }
public void PlayersToBytes() { for (int i = 0; i < 80; i++) { int[] playerIds = new int[80]; for (int j = 0; j < i; j++) { playerIds[j] = UnityEngine.Random.Range(1, 1023); } //Debug.Log($"playerIds: {string.Join(",", playerIds)}"); var matchingEnabled = UnityEngine.Random.value > 0.5f; var bytes = MatchingTrackerPlayerState.serializeBytes(i, playerIds, matchingEnabled); var frame = MatchingTrackerPlayerState.SerializeFrame(bytes); var deframe = MatchingTrackerPlayerState.DeserializeFrame(new string(frame)); Assert.That(deframe, Is.EqualTo(bytes)); int[] deser = new int[80]; var deserMatchingEnabled = MatchingTrackerPlayerState.deserializeBytes(deframe, deser); Assert.That(deser, Is.EqualTo(playerIds)); Assert.That(deserMatchingEnabled, Is.EqualTo(matchingEnabled)); } }
private void UpdateCanvas() { if (!MatchingTracker.started) { return; } if ((updateCooldown -= Time.deltaTime) > 0) { return; } updateCooldown = 1f; // show indication if player hasn't got ownership yet if (MatchingTracker.localPlayerState == null) { title.text = "Initializing, please wait warmly\n(If this persists, try rejoining.)"; return; } var matchesRemaining = 0; for (int i = 0; i < 80; i++) { MatchingTrackerPlayerState state = MatchingTracker.playerStates[i]; VRCPlayerApi p = state.GetExplicitOwner(); if (p == null || Networking.LocalPlayer == p) { toggles[i].gameObject.SetActive(false); activePlayerLastUpdate[i] = null; continue; } toggles[i].gameObject.SetActive(true); var wasMatchedWith = MatchingTracker.GetLocallyMatchedWith(p); var matchedWithUs = state.matchedWithLocalPlayer; if (wasMatchedWith) { texts[i].text = MatchingTracker.GetDisplayName(p); var seconds = Time.time - MatchingTracker.GetLastMatchedWith(p); var minutes = seconds / 60f; var hours = minutes / 60f; texts[i].text = $"{MatchingTracker.GetDisplayName(p)} (matched " + (hours > 1 ? $"{Mathf.FloorToInt(hours):D2}:{Mathf.FloorToInt(minutes):D2} ago)" : minutes > 1 ? $"{Mathf.FloorToInt(minutes):##} minutes ago)" : $"{Mathf.FloorToInt(seconds):##} seconds ago)"); } else if (matchedWithUs) { texts[i].text = $"{MatchingTracker.GetDisplayName(p)} (matched with you on their end)"; } else if (!state.matchingEnabled) { texts[i].text = $"{MatchingTracker.GetDisplayName(p)} (taking a break from matching)"; } else { texts[i].text = MatchingTracker.GetDisplayName(p); matchesRemaining++; } if (activePlayerLastUpdate[i] == MatchingTracker.GetDisplayName(p)) { // if player changed state in ui (doesn't match our internal state) if (toggles[i].isOn != lastSeenToggle[i]) { MatchingTracker.SetLocallyMatchedWith(p, toggles[i].isOn); } else { // set UI from tracker state toggles[i].isOn = wasMatchedWith; } lastSeenToggle[i] = toggles[i].isOn; } else { // wasn't the same player before activePlayerLastUpdate[i] = MatchingTracker.GetDisplayName(p); // set the UI state ignoring what it was toggles[i].isOn = wasMatchedWith; lastSeenToggle[i] = wasMatchedWith; } } title.text = $"Player Checklist ({matchesRemaining} matches remaining)"; }
// maintain ownership of exactly one of the MatchingTrackerPlayerState gameobjects private void MaintainLocalOwnership() { var localPlayerId = Networking.LocalPlayer.playerId; if (localPlayerState == null) { if ((takeOwnershipAttemptCooldown -= Time.deltaTime) < 0) { // try again after a bit. takeOwnershipAttemptCooldown = UnityEngine.Random.Range(1f, 2f); Log($"no owned MatchingTrackerPlayerState, scanning for an unowned one"); foreach (var playerState in playerStates) { // skip uninitialized states if (!playerState.IsInitialized()) { continue; } var owner = playerState.GetExplicitOwner(); if (owner == null) { Log($"taking ownership {playerState.gameObject.name}, cooldown {takeOwnershipAttemptCooldown}"); playerState.gameObject.SetActive(true); playerState.TakeExplicitOwnership(); break; } else if (owner.playerId == localPlayerId) { Log($"found ownership of {playerState.name}, setting localPlayerState"); localPlayerState = playerState; break; } } } } else { var owner = localPlayerState.GetExplicitOwner(); if (owner == null || owner.playerId != localPlayerId) { // lost ownership somehow Log($"Lost ownership of {localPlayerState.name}, nulling localPlayerState"); localPlayerState = null; } else { // make sure we don't have ownership of more than one if ((releaseOwnershipAttemptCooldown -= Time.deltaTime) < 0) { releaseOwnershipAttemptCooldown = UnityEngine.Random.Range(1f, 2f); bool foundOne = false; foreach (var playerState in playerStates) { var o = playerState.GetExplicitOwner(); if (o != null && o.playerId == localPlayerId) { if (foundOne) { Log($"uhoh, found extra owned {playerState.name}, releasing."); // release explicit ownership playerState.ownerId = -1; } foundOne = true; } } } } } }