Adds SquadService (singleton, process-local) tracking squads by the
squadId the client shares across party members, plus a user->squad index
so TryGetCompleteSquadInfo (no squadId in request) can resolve the
caller's squad. Members are lazily registered on any squad call.
- TryGetCompleteSquadInfo: returns the caller's real squad.
- SquadMemberReadyForMatch: joins the squad, records readiness/map,
returns the squad + whether everyone is ready.
- SquadMemberSelectedMap: records the member's selected map.
- DbUserService.FindByIdAsync: resolve display name for squad members.
Groundwork for the station lobby; assumes the client drives squads via
these calls with a shared squadId (to confirm with a 2-client session).
Real-time SignalR push (unknown event names) deferred; the squad is
carried in responses + TryGetCompleteSquadInfo for now.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
New console utility (net8.0, Linux/Proton + Windows) to point a client at
a server by writing backend.txt — the single value the Prospect agent
reads. Presets for PROD/PREPROD LAN and PROD internet, plus custom URL,
certificate import (native on Windows, guided with Proton-prefix
detection on Linux) and game launch. Interactive menu + scriptable CLI
(--folder/--set). Added to the solution; not built by the server CI.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Switcher presets now use the public domains (tc.nfteam.ovh:8443 /
rd-tc.nfteam.ovh:8444) so the same target works for everyone; the
unified TLS cert covers both hostnames. LAN users add a hosts entry to
avoid hairpin NAT.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
GetSignalRConnection now serves the SignalR URL on 192.168.1.136 to
clients whose remote IP is on the LAN, and keeps the public domain for
external clients. The real-time WebSocket (libwebsockets, incl. under
Proton/Wine) couldn't reach the public domain from inside the LAN
(hairpin NAT) — it failed right after the intro as "error code 5".
External friends are unaffected (still get the domain).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
On Linux the tool now actually trusts the server certificate inside the
game's Proton/Wine prefix (the wine certutil tool is broken under Proton):
it fetches the live cert from the server (backend.txt), builds the wine
serialized cert blob (SHA1 + encoded cert) and writes it to the prefix
Root store via `wine reg import`. Auto-detects the Proton wine and lists
compatdata prefixes (most-recent first) so the non-Steam-shortcut prefix
is picked correctly; the chosen prefix is remembered.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
FeatureToggles had m_isFriendsLimitEnabled=true with no positive limit,
so the client showed 'friend limit reached: 0 friends' and blocked adding
friends / squad invites. Disabled the toggle (squads/social already on).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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>
When GAMESERVER_ADDRESS ("host:port") is set, EnterMatchmaking returns
that server (SingleplayerStation=false) and EnterMatchmakingMatch's
deploy signal carries its address, so the client travels to the real
game server instead of the client-hosted station. Unset = unchanged
(normal preprod). Lets a 2nd preprod run the same :preprod image and
differ only by this env var (dedicated-server test bench).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Symptom: missions done in raid zones weren't saved -> contracts stuck on
'Objective not met', no claim possible.
Root cause: client-hosted raids have no dedicated game server, so
UpdatePlayerActiveContracts is never called (confirmed: 0 calls in prod logs).
Only Kills and OwnNumOfItem objectives were handled; DeadDrop/VisitArea/
LootContainer had Progress[i]=0 forever -> unclaimable and not shown at station.
Fix: EYContractObjectiveType.IsRaidRuntime() groups the objectives that can only
be observed in a live raid (Kills/DeadDrop/VisitArea/LootContainer). Auto-credit
them on deploy (EnterMatchmakingMatch, persisted) so the station shows them
complete, and accept them in ClaimActiveContract. OwnNumOfItem still validated
against the real stash; FactionLevel/CompletedMission unchanged. Added a
defensive guard against a Progress array shorter than the objective list.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Auto-crédit DeadDrop/VisitArea/LootContainer (+Kills) via IsRaidRuntime() — persistés au déploiement + acceptés au claim. OwnNumOfItem inchangé (validé stash).
When GAMESERVER_ADDRESS ("host:port") is set, EnterMatchmaking returns that server (SingleplayerStation=false) and EnterMatchmakingMatch's deploy signal carries its address, so the client travels to the real game server instead of the client-hosted station. Unset = unchanged (normal preprod). Lets a 2nd preprod run the same :preprod image and differ only by this env var (dedicated-server test bench). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>