UI/OnlinePage.razor
@using System;
@using Sandbox;
@using Sandbox.UI;
@using Sandbox.UI.Navigation;
@inherits Panel
@attribute [Route( "/online" )]
<root class="menu-page online-page">
<label class="page-heading">
ONLINE 1V1
</label>
@if ( _showSettings )
{
<div class="online-subheading">
LOCAL SETTINGS
</div>
<label class="page-copy">
These preferences affect only your local player.
</label>
<SettingsPanel />
<div class="menu-back" onclick=@CloseSettings>
BACK TO LOBBY
</div>
}
else if ( FlowManager is null )
{
<div class="online-status-label error">
NETWORK FLOW UNAVAILABLE
</div>
<a
href="/play"
class="menu-back"
>
BACK
</a>
}
else if (
FlowManager.OnlineState ==
OnlineFlowState.Searching
)
{
<div class="online-status-label">
SEARCHING FOR MATCH
</div>
<div class="online-spinner">
•••
</div>
<label class="page-copy">
Looking for another available One More Round player.
</label>
<div class="menu-back" onclick=@Cancel>
CANCEL
</div>
}
else if (
FlowManager.OnlineState ==
OnlineFlowState.Connecting
)
{
<div class="online-status-label">
JOINING MATCH
</div>
<div class="online-spinner">
•••
</div>
<label class="page-copy">
Connecting to an available opponent.
</label>
<div class="menu-back" onclick=@Cancel>
CANCEL
</div>
}
else if (
FlowManager.OnlineState ==
OnlineFlowState.WaitingForOpponent
)
{
<div class="online-status-label">
SEARCHING FOR OPPONENT
</div>
<div class="player-card-row">
<div class="player-card ready">
<div class="player-card-label">YOU</div>
<div class="player-card-name">@LocalConnectionName</div>
<div class="player-card-state">CONNECTED</div>
</div>
<div class="versus">
VS
</div>
<div class="player-card searching">
<div class="player-card-label">OPPONENT</div>
<div class="player-card-name">SEARCHING...</div>
<div class="player-card-state">WAITING</div>
</div>
</div>
<label class="page-copy">
Lobby open · @ConnectedPlayerCount/2 players connected
</label>
<div class="menu-primary secondary-action" onclick=@OpenSettings>
SETTINGS
</div>
<div class="menu-back" onclick=@Cancel>
CANCEL
</div>
}
else if (
FlowManager.OnlineState ==
OnlineFlowState.Lobby
)
{
<div class="online-status-label found">
PRE-MATCH LOBBY
</div>
<label class="page-copy">
The match begins only when both players are ready.
</label>
<div class="player-card-row lobby-cards">
<div class="player-card @LocalCardClass">
<div class="player-card-label">YOU</div>
<div class="player-card-name">@LocalConnectionName</div>
<div class="player-card-state">@LocalStateText</div>
</div>
<div class="versus">
VS
</div>
<div class="player-card opponent-card @OpponentCardClass">
<div class="player-card-label">OPPONENT</div>
<div class="player-card-name">@OpponentConnectionName</div>
<div class="player-card-state">@OpponentStateText</div>
</div>
</div>
<div class="lobby-weapon-panel">
<div class="setup-label">
WARMUP WEAPON
</div>
<div class="setup-selector">
<div
class="selector-arrow"
onclick=@PreviousWeapon
>
‹
</div>
<div class="selector-value">
@LocalWarmupWeapon
</div>
<div
class="selector-arrow"
onclick=@NextWeapon
>
›
</div>
</div>
<div class="lobby-note">
This selection is only for pre-match practice. Competitive round loadouts remain controlled by the game.
</div>
</div>
<div class="lobby-actions">
<div class="menu-primary warmup-action" onclick=@ToggleWarmup>
@(LocalState == PreMatchPlayerState.Warmup ? "RETURN TO LOBBY" : "WARMUP")
</div>
<div class="menu-primary secondary-action" onclick=@OpenSettings>
SETTINGS
</div>
<div class="menu-primary ready-action @(LocalState == PreMatchPlayerState.Ready ? "active" : "")" onclick=@ToggleReady>
@(LocalState == PreMatchPlayerState.Ready ? "NOT READY" : "READY")
</div>
</div>
<div class="lobby-ready-summary">
@ReadySummary
</div>
<div class="menu-back" onclick=@Cancel>
LEAVE LOBBY
</div>
}
else if (
FlowManager.OnlineState ==
OnlineFlowState.Error
)
{
<div class="online-status-label error">
MATCHMAKING ERROR
</div>
<label class="page-copy error-copy">
@FlowManager.ErrorMessage
</label>
<div class="menu-primary" onclick=@Retry>
TRY AGAIN
</div>
<div class="menu-back" onclick=@Cancel>
BACK
</div>
}
else
{
<div class="online-status-label">
READY
</div>
<a
href="/play"
class="menu-back"
>
BACK
</a>
}
</root>
@code
{
private bool _showSettings;
private MainMenuHost Host =>
MainMenuHost.Current;
private GameFlowManager FlowManager =>
Host?.
FlowManager;
private PlayerState LocalPlayer =>
Host?.
LocalPlayerState;
private PlayerState OpponentPlayer =>
Host?.
OpponentPlayerState;
private int ConnectedPlayerCount =>
Host?.
ConnectedPlayerCount ??
0;
private string LocalConnectionName =>
Host?.
LocalConnectionName ??
"YOU";
private string OpponentConnectionName =>
Host?.
OpponentConnectionName ??
"OPPONENT";
private PreMatchPlayerState LocalState =>
LocalPlayer?.
PreMatchState ??
PreMatchPlayerState.Lobby;
private PreMatchPlayerState OpponentState =>
OpponentPlayer?.
PreMatchState ??
PreMatchPlayerState.Lobby;
private string LocalStateText =>
StateText(
LocalState
);
private string OpponentStateText =>
StateText(
OpponentState
);
private string LocalCardClass =>
StateClass(
LocalState
);
private string OpponentCardClass =>
StateClass(
OpponentState
);
private string LocalWarmupWeapon =>
Host?.
GetPreMatchWeaponName(
LocalPlayer
) ??
"NO WEAPON";
private string ReadySummary
{
get
{
bool localReady =
LocalState ==
PreMatchPlayerState.Ready;
bool opponentReady =
OpponentState ==
PreMatchPlayerState.Ready;
if (
localReady &&
opponentReady
)
return "BOTH READY · STARTING MATCH";
if ( localReady )
return "WAITING FOR OPPONENT";
if ( opponentReady )
return "OPPONENT READY · YOUR DECISION";
return "BOTH PLAYERS NOT READY";
}
}
private string StateText(
PreMatchPlayerState state
)
{
return state switch
{
PreMatchPlayerState.Warmup =>
"WARMUP",
PreMatchPlayerState.Ready =>
"READY",
_ =>
"IN LOBBY"
};
}
private string StateClass(
PreMatchPlayerState state
)
{
return state switch
{
PreMatchPlayerState.Warmup =>
"practicing",
PreMatchPlayerState.Ready =>
"ready",
_ =>
""
};
}
private void PreviousWeapon() =>
Host?.
CyclePreMatchWeapon(
-1
);
private void NextWeapon() =>
Host?.
CyclePreMatchWeapon(
1
);
private void ToggleWarmup() =>
Host?.
TogglePreMatchWarmup();
private void ToggleReady() =>
Host?.
TogglePreMatchReady();
private void OpenSettings()
{
_showSettings =
true;
}
private void CloseSettings()
{
_showSettings =
false;
}
private void Retry()
{
_showSettings =
false;
Host?.
FindMatch();
}
private void Cancel()
{
_showSettings =
false;
Host?.
CancelMatchmaking();
}
protected override int BuildHash()
{
HashCode hash =
new();
hash.Add(
_showSettings
);
hash.Add(
FlowManager?.
OnlineState
);
hash.Add(
FlowManager?.
ErrorMessage
);
hash.Add(
ConnectedPlayerCount
);
hash.Add(
LocalConnectionName
);
hash.Add(
OpponentConnectionName
);
hash.Add(
LocalState
);
hash.Add(
OpponentState
);
hash.Add(
LocalPlayer?.
WarmupWeaponIndex
);
hash.Add(
OpponentPlayer?.
WarmupWeaponIndex
);
return hash.ToHashCode();
}
}