Game/MansionGame.Slots.cs

Manages player slots and associated colors for MansionGame. Stores a networked list of connection GUIDs per slot, assigns/releases slots for connections, looks up a connection's slot index, and maps slots to colors.

Networking
using System;
using Sandbox;

namespace BrickJam;

public sealed partial class MansionGame
{
	public static readonly Color[] SlotToColor =
	{
		Color.Red, Color.Green, Color.Blue, Color.Yellow
	};

	/// <summary>
	/// Connection id occupying each player slot. <see cref="Guid.Empty"/> means the slot is free.
	/// Replaces the legacy <c>IList&lt;IClient&gt; ClientSlots</c>. Networked so clients can resolve
	/// player colours locally.
	/// </summary>
	// FromHost: slots are assigned host-side (AssignSlot/ReleaseSlot) on the unowned manager, so plain
	// [Sync] wouldn't reach clients - which would leave player colours wrong/default on other clients.
	[Sync( SyncFlags.FromHost )] public NetList<Guid> ClientSlots { get; set; } = new();

	/// <summary>
	/// Assign the first free slot to a connection. Host-only. Replaces <c>GiveSlot( IClient )</c>.
	/// </summary>
	public void GiveSlot( Connection channel )
	{
		var firstEmptySlot = ClientSlots.IndexOf( Guid.Empty );

		if ( firstEmptySlot == -1 )
		{
			ClientSlots.Add( channel.Id );
			return;
		}

		ClientSlots[firstEmptySlot] = channel.Id;
	}

	/// <summary>
	/// Free the slot held by a connection. Host-only. Replaces <c>ReleaseSlot( IClient )</c>.
	/// </summary>
	public void ReleaseSlot( Connection channel )
	{
		var slot = ClientSlots.IndexOf( channel.Id );
		if ( slot != -1 )
			ClientSlots[slot] = Guid.Empty;
	}

	/// <summary>
	/// The slot index occupied by a connection, or -1 if none.
	/// </summary>
	public int GetSlot( Connection channel )
	{
		if ( channel is null )
			return -1;

		return ClientSlots.IndexOf( channel.Id );
	}

	/// <summary>
	/// Resolve the colour for a connection from its slot. Replaces the old
	/// <c>ClientExtension.GetColor( IClient )</c>.
	/// </summary>
	public Color GetColor( Connection channel )
	{
		var slot = GetSlot( channel );
		if ( slot < 0 )
			return Color.Gray;

		return SlotToColor[slot % SlotToColor.Length];
	}
}