@ -8,7 +8,7 @@ using Epic.OnlineServices.RTCAudio;
using UnityEngine ;
using UnityEngine ;
/// <summary>
/// <summary>
/// Generic re- usable cross-platform class to provide common voice chat functionality based on the EOS Voice Chat service.
/// Generic reusable cross-platform class to provide common voice chat functionality based on the EOS Voice Chat service.
/// This class does not know anything about EOS platform initialization or authentication; it just takes the required
/// This class does not know anything about EOS platform initialization or authentication; it just takes the required
/// EOS interfaces and exposes a number of game-related voice functions.
/// EOS interfaces and exposes a number of game-related voice functions.
/// </summary>
/// </summary>
@ -20,7 +20,6 @@ public class EOSVoiceChat
private readonly RTCInterface rtcInterface ;
private readonly RTCInterface rtcInterface ;
private readonly RTCAudioInterface audioInterface ;
private readonly RTCAudioInterface audioInterface ;
private readonly Func < ProductUserId > localUserProvider ;
private readonly Func < ProductUserId > localUserProvider ;
private readonly IProductUserMapper productUserMapper ;
private readonly Dictionary < ProductUserId , ChatUser > chatUsers = new Dictionary < ProductUserId , ChatUser > ( ) ;
private readonly Dictionary < ProductUserId , ChatUser > chatUsers = new Dictionary < ProductUserId , ChatUser > ( ) ;
@ -36,13 +35,12 @@ public class EOSVoiceChat
/// </summary>
/// </summary>
public EOSVoiceChat (
public EOSVoiceChat (
LobbyInterface lobbyInterface , RTCInterface rtcInterface , RTCAudioInterface audioInterface ,
LobbyInterface lobbyInterface , RTCInterface rtcInterface , RTCAudioInterface audioInterface ,
Func < ProductUserId > localUserProvider , IProductUserMapper productUserMapper )
Func < ProductUserId > localUserProvider )
{
{
this . lobbyInterface = lobbyInterface ;
this . lobbyInterface = lobbyInterface ;
this . rtcInterface = rtcInterface ;
this . rtcInterface = rtcInterface ;
this . audioInterface = audioInterface ;
this . audioInterface = audioInterface ;
this . localUserProvider = localUserProvider ;
this . localUserProvider = localUserProvider ;
this . productUserMapper = productUserMapper ;
}
}
/// <summary>
/// <summary>
@ -115,7 +113,7 @@ public class EOSVoiceChat
chatUsers . Clear ( ) ;
chatUsers . Clear ( ) ;
SubscribeToRoomNotifications ( ) ;
SubscribeToRoomNotifications ( ) ;
connectArgs . onCompleted ? . Invoke ( true ) ;
connectArgs . onCompleted ? . Invoke ( true ) ; // NOTE: this callback may come too soon, we probably don't have the list of participants populated yet...
break ;
break ;
case Result . LobbyLobbyAlreadyExists :
case Result . LobbyLobbyAlreadyExists :
// This can happen if two clients try to create the same lobby at the same time, a classic race condition.
// This can happen if two clients try to create the same lobby at the same time, a classic race condition.
@ -146,7 +144,7 @@ public class EOSVoiceChat
chatUsers . Clear ( ) ;
chatUsers . Clear ( ) ;
SubscribeToRoomNotifications ( ) ;
SubscribeToRoomNotifications ( ) ;
connectArgs . onCompleted ? . Invoke ( true ) ;
connectArgs . onCompleted ? . Invoke ( true ) ; // NOTE: this callback may come too soon, we probably don't have the list of participants populated yet...
break ;
break ;
default :
default :
connectedLobbyId = null ;
connectedLobbyId = null ;
@ -218,21 +216,18 @@ public class EOSVoiceChat
/// Mute or unmute a specific remove player. This can be used to filter out specific players in the chat lobby,
/// Mute or unmute a specific remove player. This can be used to filter out specific players in the chat lobby,
/// or for manually muting toxic players.
/// or for manually muting toxic players.
/// </summary>
/// </summary>
public void SetRemoteMuted ( string remotePlayerId , bool muted )
public void SetRemoteMuted ( ProductUserId remoteUser , bool muted )
{
{
if ( ! IsConnected )
if ( ! IsConnected )
return ;
return ;
productUserMapper . MapPlatformIdToProductUser ( remotePlayerId , remoteProductUser = >
{
audioInterface . UpdateReceiving ( new UpdateReceivingOptions
audioInterface . UpdateReceiving ( new UpdateReceivingOptions
{
{
LocalUserId = localUserProvider . Invoke ( ) ,
LocalUserId = localUserProvider . Invoke ( ) ,
ParticipantId = remoteProduct User ,
ParticipantId = remoteUser ,
RoomName = rtcRoomName ,
RoomName = rtcRoomName ,
AudioEnabled = ! muted ,
AudioEnabled = ! muted ,
} , null , data = > { } ) ;
} , null , data = > { } ) ;
} ) ;
}
}
/// <summary>
/// <summary>
@ -272,16 +267,13 @@ public class EOSVoiceChat
}
}
/// <summary>
/// <summary>
/// Whether the requested play er is currently talking or not.
/// This can be either the local player or a remote play er.
/// Whether the requested us er is currently talking or not.
/// This can be either the local player or a remote us er.
/// </summary>
/// </summary>
public bool IsPlayerTalking ( string playerId )
public bool IsUserTalking ( ProductUserId user )
{
{
foreach ( var chatUser in chatUsers . Values )
if ( chatUsers . TryGetValue ( user , out var chatUser ) )
{
{
if ( chatUser . platformPlayerId ! = playerId )
continue ;
return chatUser . audioStatus = = RTCAudioStatus . Enabled & & chatUser . isSpeaking ;
return chatUser . audioStatus = = RTCAudioStatus . Enabled & & chatUser . isSpeaking ;
}
}
@ -382,7 +374,6 @@ public class EOSVoiceChat
return ;
return ;
var chatUser = new ChatUser ( data . ParticipantId ) ;
var chatUser = new ChatUser ( data . ParticipantId ) ;
productUserMapper . MapProductUserToPlatformId ( data . ParticipantId , pid = > chatUser . platformPlayerId = pid ) ;
chatUsers . Add ( data . ParticipantId , chatUser ) ;
chatUsers . Add ( data . ParticipantId , chatUser ) ;
break ;
break ;
case RTCParticipantStatus . Left :
case RTCParticipantStatus . Left :
@ -420,7 +411,6 @@ public class EOSVoiceChat
{
{
public readonly ProductUserId productUserId ;
public readonly ProductUserId productUserId ;
public string platformPlayerId ;
public RTCAudioStatus audioStatus ;
public RTCAudioStatus audioStatus ;
public bool isSpeaking ;
public bool isSpeaking ;