using System;
using Unity.BossRoom.Gameplay.Configuration;
using Unity.BossRoom.Utils;
using Unity.Netcode;
namespace Unity.BossRoom.Gameplay.GameState
{
///
/// Common data and RPCs for the CharSelect stage.
///
public class NetworkCharSelection : NetworkBehaviour
{
public enum SeatState : byte
{
Inactive,
Active,
LockedIn,
}
///
/// Describes one of the players in the lobby, and their current character-select status.
///
///
/// Putting FixedString inside an INetworkSerializeByMemcpy struct is not recommended because it will lose the
/// bandwidth optimization provided by INetworkSerializable -- an empty FixedString128Bytes serialized normally
/// or through INetworkSerializable will use 4 bytes of bandwidth, but inside an INetworkSerializeByMemcpy, that
/// same empty value would consume 132 bytes of bandwidth.
///
public struct LobbyPlayerState : INetworkSerializable, IEquatable
{
public ulong ClientId;
private FixedPlayerName m_PlayerName; // I'm sad there's no 256Bytes fixed list :(
public int PlayerNumber; // this player's assigned "P#". (0=P1, 1=P2, etc.)
public int SeatIdx; // the latest seat they were in. -1 means none
public float LastChangeTime;
public SeatState SeatState;
public LobbyPlayerState(ulong clientId, string name, int playerNumber, SeatState state, int seatIdx = -1, float lastChangeTime = 0)
{
ClientId = clientId;
PlayerNumber = playerNumber;
SeatState = state;
SeatIdx = seatIdx;
LastChangeTime = lastChangeTime;
m_PlayerName = new FixedPlayerName();
PlayerName = name;
}
public string PlayerName
{
get => m_PlayerName;
private set => m_PlayerName = value;
}
public void NetworkSerialize(BufferSerializer serializer) where T : IReaderWriter
{
serializer.SerializeValue(ref ClientId);
serializer.SerializeValue(ref m_PlayerName);
serializer.SerializeValue(ref PlayerNumber);
serializer.SerializeValue(ref SeatState);
serializer.SerializeValue(ref SeatIdx);
serializer.SerializeValue(ref LastChangeTime);
}
public bool Equals(LobbyPlayerState other)
{
return ClientId == other.ClientId &&
m_PlayerName.Equals(other.m_PlayerName) &&
PlayerNumber == other.PlayerNumber &&
SeatIdx == other.SeatIdx &&
LastChangeTime.Equals(other.LastChangeTime) &&
SeatState == other.SeatState;
}
}
private NetworkList m_LobbyPlayers;
public Avatar[] AvatarConfiguration;
private void Awake()
{
m_LobbyPlayers = new NetworkList();
}
///
/// Current state of all players in the lobby.
///
public NetworkList LobbyPlayers => m_LobbyPlayers;
///
/// When this becomes true, the lobby is closed and in process of terminating (switching to gameplay).
///
public NetworkVariable IsLobbyClosed { get; } = new NetworkVariable(false);
///
/// Server notification when a client requests a different lobby-seat, or locks in their seat choice
///
public event Action OnClientChangedSeat;
///
/// RPC to notify the server that a client has chosen a seat.
///
[Rpc(SendTo.Server, RequireOwnership = false)]
public void ServerChangeSeatRpc(ulong clientId, int seatIdx, bool lockedIn)
{
OnClientChangedSeat?.Invoke(clientId, seatIdx, lockedIn);
}
}
}