public async Task NewUserConnectsAndStreamsData() { Mock <IHubCallerClients <ISpectatorClient> > mockClients = new Mock <IHubCallerClients <ISpectatorClient> >(); Mock <ISpectatorClient> mockReceiver = new Mock <ISpectatorClient>(); mockClients.Setup(clients => clients.All).Returns(mockReceiver.Object); mockClients.Setup(clients => clients.Group(SpectatorHub.GetGroupId(streamer_id))).Returns(mockReceiver.Object); Mock <HubCallerContext> mockContext = new Mock <HubCallerContext>(); mockContext.Setup(context => context.UserIdentifier).Returns(streamer_id.ToString()); hub.Context = mockContext.Object; hub.Clients = mockClients.Object; await hub.BeginPlaySession(new SpectatorState(88)); // check all other users were informed that streaming began mockClients.Verify(clients => clients.All, Times.Once); mockReceiver.Verify(clients => clients.UserBeganPlaying(streamer_id, It.Is <SpectatorState>(m => m.Equals(state))), Times.Once()); // check state data was added var cacheState = await cache.GetStringAsync(SpectatorHub.GetStateId(streamer_id)); Assert.Equal(state, JsonConvert.DeserializeObject <SpectatorState>(cacheState)); var data = new FrameDataBundle(new[] { new LegacyReplayFrame(1234, 0, 0, ReplayButtonState.None) }); // check streaming data is propagating to watchers await hub.SendFrameData(data); mockReceiver.Verify(clients => clients.UserSentFrames(streamer_id, data)); }
private void userSentFrames(int userId, FrameDataBundle data) { if (userId != targetUser.Id) { return; } // this should never happen as the server sends the user's state on watching, // but is here as a safety measure. if (replay == null) { return; } foreach (var frame in data.Frames) { IConvertibleReplayFrame convertibleFrame = rulesetInstance.CreateConvertibleReplayFrame(); convertibleFrame.FromLegacy(frame, beatmap.Value.Beatmap); var convertedFrame = (ReplayFrame)convertibleFrame; convertedFrame.Time = frame.Time; replay.Frames.Add(convertedFrame); } }
private void userSentFrames(int userId, FrameDataBundle bundle) { lock (stateLock) { if (!userMap.ContainsKey(userId)) { return; } if (!gameplayStates.TryGetValue(userId, out var gameplayState)) { return; } // The ruleset instance should be guaranteed to be in sync with the score via ScoreLock. Debug.Assert(gameplayState.Ruleset != null && gameplayState.Ruleset.RulesetInfo.Equals(gameplayState.Score.ScoreInfo.Ruleset)); foreach (var frame in bundle.Frames) { IConvertibleReplayFrame convertibleFrame = gameplayState.Ruleset.CreateConvertibleReplayFrame(); convertibleFrame.FromLegacy(frame, gameplayState.Beatmap.Beatmap); var convertedFrame = (ReplayFrame)convertibleFrame; convertedFrame.Time = frame.Time; gameplayState.Score.Replay.Frames.Add(convertedFrame); } } }
private void userSentFrames(int userId, FrameDataBundle data) { // this is not scheduled as it handles propagation of frames even when in a child screen (at which point we are not alive). // probably not the safest way to handle this. if (userId != targetUser.Id) { return; } lock (scoreLock) { // this should never happen as the server sends the user's state on watching, // but is here as a safety measure. if (score == null) { return; } // rulesetInstance should be guaranteed to be in sync with the score via scoreLock. Debug.Assert(rulesetInstance != null && rulesetInstance.RulesetInfo.Equals(score.ScoreInfo.Ruleset)); foreach (var frame in data.Frames) { IConvertibleReplayFrame convertibleFrame = rulesetInstance.CreateConvertibleReplayFrame(); convertibleFrame.FromLegacy(frame, beatmap.Value.Beatmap); var convertedFrame = (ReplayFrame)convertibleFrame; convertedFrame.Time = frame.Time; score.Replay.Frames.Add(convertedFrame); } } }
private void userSentFrames(int userId, FrameDataBundle bundle) { if (userId != score.ScoreInfo.User.Id) { return; } if (!LoadedBeatmapSuccessfully) { return; } if (!this.IsCurrentScreen()) { return; } bool isFirstBundle = score.Replay.Frames.Count == 0; foreach (var frame in bundle.Frames) { IConvertibleReplayFrame convertibleFrame = GameplayRuleset.CreateConvertibleReplayFrame(); convertibleFrame.FromLegacy(frame, GameplayBeatmap.PlayableBeatmap); var convertedFrame = (ReplayFrame)convertibleFrame; convertedFrame.Time = frame.Time; score.Replay.Frames.Add(convertedFrame); } if (isFirstBundle && score.Replay.Frames.Count > 0) { NonFrameStableSeek(score.Replay.Frames[0].Time); } }
private void handleIncomingFrames(int userId, FrameDataBundle bundle) { if (userScores.TryGetValue(userId, out var trackedData)) { trackedData.LastHeader = bundle.Header; trackedData.UpdateScore(scoreProcessor, scoringMode.Value); } }
private void onNewFrames(int userId, FrameDataBundle frames) { Logger.Log($"Received {frames.Frames.Count()} new frames ({string.Join(',', frames.Frames.Select(f => ((int)f.Time).ToString()))})"); foreach (var legacyFrame in frames.Frames) { var frame = new TestReplayFrame(); frame.FromLegacy(legacyFrame, null, null); replay.Frames.Add(frame); } }
public void TestFinalFrameInBundleHasHeader() { FrameDataBundle lastBundle = null; AddStep("bind to client", () => spectatorClient.OnNewFrames += (_, bundle) => lastBundle = bundle); start(-1234); sendFrames(); finish(); AddUntilStep("bundle received", () => lastBundle != null); AddAssert("first frame does not have header", () => lastBundle.Frames[0].Header == null); AddAssert("last frame has header", () => lastBundle.Frames[^ 1].Header != null);
public void SendFrames(int userId, int index, int count) { var frames = new List <LegacyReplayFrame>(); for (int i = index; i < index + count; i++) { var buttonState = i == index + count - 1 ? ReplayButtonState.None : ReplayButtonState.Left1; frames.Add(new LegacyReplayFrame(i * 100, RNG.Next(0, 512), RNG.Next(0, 512), buttonState)); } var bundle = new FrameDataBundle(new ScoreInfo { Combo = index + count }, frames); ((ISpectatorClient)this).UserSentFrames(userId, bundle); }
public void SendFrames(int index, int count) { var frames = new List <LegacyReplayFrame>(); for (int i = index; i < index + count; i++) { var buttonState = i == index + count - 1 ? ReplayButtonState.None : ReplayButtonState.Left1; frames.Add(new LegacyReplayFrame(i * 100, RNG.Next(0, 512), RNG.Next(0, 512), buttonState)); } var bundle = new FrameDataBundle(new ScoreInfo(), frames); ((ISpectatorClient)this).UserSentFrames(StreamingUser.Id, bundle); if (!sentState) { sendState(beatmapId); } }
public void SendFrames(int userId, int count) { var frames = new List <LegacyReplayFrame>(); int currentFrameIndex = userNextFrameDictionary[userId]; int lastFrameIndex = currentFrameIndex + count - 1; for (; currentFrameIndex <= lastFrameIndex; currentFrameIndex++) { // This is done in the next frame so that currentFrameIndex is updated to the correct value. if (frames.Count == FRAME_BUNDLE_SIZE) { flush(); } var buttonState = currentFrameIndex == lastFrameIndex ? ReplayButtonState.None : ReplayButtonState.Left1; frames.Add(new LegacyReplayFrame(currentFrameIndex * 100, RNG.Next(0, 512), RNG.Next(0, 512), buttonState)); } flush(); userNextFrameDictionary[userId] = currentFrameIndex; void flush() { if (frames.Count == 0) { return; } var bundle = new FrameDataBundle(new ScoreInfo { Combo = currentFrameIndex }, frames.ToArray()); ((ISpectatorClient)this).UserSentFrames(userId, bundle); frames.Clear(); } }
private void handleIncomingFrames(int userId, FrameDataBundle bundle) => Schedule(() => { if (!UserScores.TryGetValue(userId, out var trackedData))
public Task SendFrames(FrameDataBundle data) => connection.SendAsync(nameof(ISpectatorServer.SendFrameData), data);
public async Task SendFrameData(FrameDataBundle data) { Console.WriteLine($"Receiving frame data ({data.Frames.First()}).."); await Clients.Group(GetGroupId(currentContextUserId)).UserSentFrames(currentContextUserId, data); }
protected override Task SendFramesInternal(FrameDataBundle data) => ((ISpectatorClient)this).UserSentFrames(api.LocalUser.Value.Id, data);
public async Task SendFrameData(FrameDataBundle data) { await Clients.Group(GetGroupId(CurrentContextUserId)).UserSentFrames(CurrentContextUserId, data); }
Task ISpectatorClient.UserSentFrames(int userId, FrameDataBundle data) { Console.WriteLine($"{connection.ConnectionId} Received frames from {userId}: {data.Frames.First()}"); return(Task.CompletedTask); }