You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

115 lines
4.2 KiB
C#

1 week ago
using System;
using Unity.BossRoom.Gameplay.Configuration;
using Unity.BossRoom.Utils;
using Unity.Netcode;
namespace Unity.BossRoom.Gameplay.GameState
{
/// <summary>
/// Common data and RPCs for the CharSelect stage.
/// </summary>
public class NetworkCharSelection : NetworkBehaviour
{
public enum SeatState : byte
{
Inactive,
Active,
LockedIn,
}
/// <summary>
/// Describes one of the players in the lobby, and their current character-select status.
/// </summary>
/// <remarks>
/// 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.
/// </remarks>
public struct LobbyPlayerState : INetworkSerializable, IEquatable<LobbyPlayerState>
{
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<T>(BufferSerializer<T> 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<LobbyPlayerState> m_LobbyPlayers;
public Avatar[] AvatarConfiguration;
private void Awake()
{
m_LobbyPlayers = new NetworkList<LobbyPlayerState>();
}
/// <summary>
/// Current state of all players in the lobby.
/// </summary>
public NetworkList<LobbyPlayerState> LobbyPlayers => m_LobbyPlayers;
/// <summary>
/// When this becomes true, the lobby is closed and in process of terminating (switching to gameplay).
/// </summary>
public NetworkVariable<bool> IsLobbyClosed { get; } = new NetworkVariable<bool>(false);
/// <summary>
/// Server notification when a client requests a different lobby-seat, or locks in their seat choice
/// </summary>
public event Action<ulong, int, bool> OnClientChangedSeat;
/// <summary>
/// RPC to notify the server that a client has chosen a seat.
/// </summary>
[Rpc(SendTo.Server, RequireOwnership = false)]
public void ServerChangeSeatRpc(ulong clientId, int seatIdx, bool lockedIn)
{
OnClientChangedSeat?.Invoke(clientId, seatIdx, lockedIn);
}
}
}