A UI Razor panel that lists occupied player seats and renders a SeatTag component for each. It queries the active CardGame from the scene and rebuilds only when the set of occupied seats changes by hashing their indexes.
@namespace CardGames
@using Sandbox
@using Sandbox.UI
@using System
@using System.Linq
@inherits Panel
@*
Hosts a SeatTag over each occupied seat's hand. Generic across games - the tags read names, chips and
per-seat badges (CardGame.SeatBadges) and position themselves in the world. This panel just decides
which seats exist; each tag handles its own placement and content.
*@
<root class="players">
@if ( Game is { } game )
{
@foreach ( var s in game.Seats.Where( s => s.Occupied ).OrderBy( s => s.Index ) )
{
var seat = s;
<SeatTag Seat=@seat />
}
}
</root>
@code
{
private CardGame Game => Sandbox.Game.ActiveScene?.Get<GameDirector>()?.ActiveGame;
// Re-list only when the set of occupied seats changes; the tags repaint themselves otherwise.
protected override int BuildHash()
{
if ( Game is not { } game ) return 0;
int h = 0;
foreach ( var s in game.Seats.Where( s => s.Occupied ) )
h = HashCode.Combine( h, s.Index );
return h;
}
}