fix(matchmaking): deploy signal targets only the deploying player
Build & Deploy / build (push) Successful in 32s

EnterMatchmakingMatch broadcast OnSquadMatchmakingSuccess to Clients.All,
so one player deploying pulled every connected player into the match.
Map each player to their SignalR connection (GetSignalRConnection tags the
URL with uid; CycleHub records it via a SignalRConnectionRegistry) and
send the deploy signal only to that connection (broadcast fallback if
unmapped). Also enable m_automaticImportPlatformFriends (Steam friends).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-14 17:56:22 +02:00
co-authored by Claude Opus 4.8
parent 8057fcae47
commit 55a9571958
6 changed files with 77 additions and 10 deletions
@@ -24,13 +24,15 @@ public class EnterMatchmakingMatchFunction : ICloudScriptFunction<FYEnterMatchAz
private readonly IHubContext<CycleHub> _hubContext;
private readonly UserDataService _userDataService;
private readonly TitleDataService _titleDataService;
private readonly SignalRConnectionRegistry _registry;
public EnterMatchmakingMatchFunction(IHubContext<CycleHub> hubContext, IHttpContextAccessor httpContextAccessor, UserDataService userDataService, TitleDataService titleDataService)
public EnterMatchmakingMatchFunction(IHubContext<CycleHub> hubContext, IHttpContextAccessor httpContextAccessor, UserDataService userDataService, TitleDataService titleDataService, SignalRConnectionRegistry registry)
{
_httpContextAccessor = httpContextAccessor;
_hubContext = hubContext;
_userDataService = userDataService;
_titleDataService = titleDataService;
_registry = registry;
}
public async Task<FYEnterMatchmakingResult> ExecuteAsync(FYEnterMatchAzureFunction request)
@@ -94,11 +96,20 @@ public class EnterMatchmakingMatchFunction : ICloudScriptFunction<FYEnterMatchAz
}
);
await _hubContext.Clients.All.SendAsync("OnSquadMatchmakingSuccess", new OnSquadMatchmakingSuccessMessage {
// Send the "matchmaking succeeded / travel to match" signal only to the deploying
// player (via their mapped SignalR connection) — broadcasting to Clients.All made
// every connected player travel too. Fall back to broadcast only if the connection
// isn't mapped yet.
var deployMessage = new OnSquadMatchmakingSuccessMessage {
Success = true,
SessionID = request.MapName, // TODO: Need to implement TryGetCompleteSquadInfo and pass squad info
SessionID = request.MapName, // TODO: pass real squad session info
SquadID = request.SquadId,
});
};
var connectionId = _registry.GetConnection(userId);
if (connectionId != null)
await _hubContext.Clients.Client(connectionId).SendAsync("OnSquadMatchmakingSuccess", deployMessage);
else
await _hubContext.Clients.All.SendAsync("OnSquadMatchmakingSuccess", deployMessage);
return new FYEnterMatchmakingResult
{
@@ -2,6 +2,7 @@ using System.Net;
using System.Net.Sockets;
using Microsoft.Extensions.Options;
using Prospect.Server.Api.Config;
using Prospect.Server.Api.Services.Auth.Extensions;
using Prospect.Server.Api.Services.CloudScript.Models;
namespace Prospect.Server.Api.Services.CloudScript.Functions;
@@ -43,7 +44,13 @@ public class GetSignalRConnection : ICloudScriptFunction<FYGetSignalRConnection,
catch { /* keep the configured URL on any parsing issue */ }
}
_logger.LogInformation("GetSignalRConnection: remoteIp={Remote} lan={Lan} -> {Url}", remote, lan, url);
// Tag the connection with the player id so the hub can map connection -> user and
// target server messages (deploy signal) instead of broadcasting to everyone.
var userId = _httpContextAccessor.HttpContext?.User.FindAuthUserId();
if (!string.IsNullOrEmpty(userId))
url += (url.Contains('?') ? "&" : "?") + "uid=" + Uri.EscapeDataString(userId);
_logger.LogInformation("GetSignalRConnection: remoteIp={Remote} lan={Lan} uid={Uid} -> {Url}", remote, lan, userId, url);
return Task.FromResult(new FYGetSignalRConnectionResult
{
File diff suppressed because one or more lines are too long