Skip to main content

Lobby

The Lobby profile card shows the signed-in player's name and level. The profile is loaded during startup, so the Lobby normally opens with it ready; returning from a mission or another scene shows the updated profile with nothing to reload.

You useIt gives you
IProjectVLobbyScreenThe screen contract: observe the profile card
ProjectVLobbyViewWhat to draw: loading state and the profile
ProjectVLobbyProfileThe player's name and level

The screen has no commands: observe it and render. See Screen contracts for how screens work in general.

Quick startโ€‹

using System;
using SilverTiger.ProjectV.Unity.Presentation.Lobby;
using UnityEngine;
using VContainer;

public sealed class LobbyProfileCard : MonoBehaviour
{
private IProjectVLobbyScreen lobby = null!;
private IDisposable? observation;

[Inject]
public void Construct(IProjectVLobbyScreen screen) => lobby = screen;

private void OnEnable()
{
ShowLoading(null); // until the first Render call
observation = lobby.Observe(Render);
}

private void OnDisable()
{
observation?.Dispose();
observation = null;
}

// Always called on the Unity main thread.
private void Render(ProjectVLobbyView view)
{
if (view.IsLoading)
{
ShowLoading(view.LoadError); // null while loading; an error code after a failed load
return;
}
ShowProfile(view.Profile!.DisplayName, view.Profile.Level);
}

// Retry button shown with a load error.
public void OnRetryClicked()
{
observation?.Dispose();
observation = lobby.Observe(Render);
}

private void ShowLoading(string? loadError) { }
private void ShowProfile(string displayName, long level) { }
}

That is the whole card: observe and draw. Render runs again only when the profile changes, for example after a mission raised the player's level.

What to drawโ€‹

Render receives a ProjectVLobbyView:

MemberTypeUse it for
IsLoadingboolTrue while no profile is shown: before the first load, after a failed load, and after sign-out. Show a spinner
LoadErrorstring?The error code of a failed load, or null. Not player text: show your own "could not load" message with Retry, and keep the code for logs
ProfileProjectVLobbyProfile?The profile; null while IsLoading

lobby.Current holds the same view.

For the ProjectVLobbyProfile:

To showRead
The player's nameDisplayName (falls back to Username when the player has none)
The levelLevel, 1 or higher, as the server sent it
The avatarYour default avatar. AvatarUrl is always empty for now
The avatar frameNothing yet. AvatarFrameId is always null for now

UserId is the account ID; do not show it.

When it failsโ€‹

SituationWhat the view doesWhat the player sees
The first load failedIsLoading true with LoadError setYour load-error message with Retry
A later refresh failedThe profile is dropped; back to IsLoading with LoadError setThe same; the old profile is not kept
The player signed outIsLoading true, LoadError nullNothing; the game is going to Login

Retry by disposing the observation and calling Observe again, as OnRetryClicked does. Every Observe call loads the profile when needed.

Rulesโ€‹

  • Show your loading state before calling Observe; the first Render call can come a moment later.
  • Show Level as the server sent it. Never work it out from local progress.
  • Do not refresh on Lobby entry. Observe loads the profile when needed, and usually it is already there.

Common mistakesโ€‹

  • Showing LoadError to the player. It is an error code.
  • Loading the avatar from AvatarUrl. It is always empty for now; show the default avatar.
  • Keeping the old profile on screen after a failed refresh. The view goes back to loading; draw what Render gives you.
  • Not disposing the observation. Keep the IDisposable from Observe and dispose it in OnDisable or OnDestroy.

Presenterโ€‹

IProjectVLobbyPresenter is the lower-level interface behind the screen contract. Pages normally use IProjectVLobbyScreen; use the presenter only if you need its extra detail:

MemberReturnsUse it for
SubscribeAsync(listener)Task<IDisposable>The current ProjectVLobbySnapshot, then every change
RefreshAsync(token)ProjectVLobbyCommandResultLoad the profile; calls run one at a time
CurrentProjectVLobbySnapshotThe latest state

The snapshot has Status (Empty, Refreshing, Ready, Failed), Profile, IsReady and a full ProjectVLobbyError with Category, Code, RequestId and LocalizationKey (projectv.lobby.<category>). RefreshAsync does not throw for a failed load: IsSuccess is false when the load failed, was cancelled (PROJECTV_LOBBY_CANCELLED), or the player signed out meanwhile.

Presenter listeners may run off the Unity main thread; switch to the main thread (for example await UniTask.SwitchToMainThread()) before touching Unity objects. The screen's Render does this for you.