UI/Players.razor

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;
	}
}