Access
Connect cross-platform accounts & identity management
using AccelByte.Api;
using AccelByte.Core;
using AccelByte.Models;
AccelBytePlugin.GetLobby().InvitedToParty += result => {};
AccelBytePlugin.GetLobby().JoinedParty += result => {};
AccelBytePlugin.GetLobby().KickedFromParty += result =>{};
AccelBytePlugin.GetLobby().LeaveFromParty += result =>{};
AccelBytePlugin.GetLobby().RejectedPartyInvitation += result =>{};
AccelBytePlugin.GetLobby().CreateParty(result =>
{
// If there is not an error, display the success information
if (!result.IsError)
{
Debug.Log("Successfully create a party");
}
});
string userId;
AccelBytePlugin.GetLobby().InviteToParty(userId, result =>
{
if (!result.IsError)
Debug.Log("Successfully invite an invitee");
}
});
string userId;
AccelBytePlugin.GetLobby().KickPartyMember(userId, result =>
{
if (result.IsError)
{
Debug.Log($"Successfully kick member from party");
}
});
AccelBytePlugin.GetLobby().LeaveParty(result =>
{
// If there is not an error, display the success information
if (!result.IsError)
{
Debug.Log("Successfully leave from party");
}
});
string userId;
AccelBytePlugin.GetLobby().PromotePartyLeader(userId, result =>
{
if (!result.IsError)
{
Debug.Log("Successfully promote member to be a party leader");
}
});
PartyInvitation partyInvitation;
AccelBytePlugin.GetLobby().JoinParty(partyInvitation.partyID, partyInvitation.invitationToken, result =>
{
if (!result.IsError)
{
Debug.Log("Successfully join the party");
}
});
PartyInvitation partyInvitation;
AccelBytePlugin.GetLobby().RejectPartyInvitation(partyInvitation.partyID, partyInvitation.invitationToken, result =>
{
if (result.IsError)
{
Debug.Log("Successfully reject the party invitation");
}
});
string[] usersIdList;
AccelBytePlugin.GetUser().BulkGetUserInfo(usersIdList, result => {
// Loop the result's Users Data, return in BaseUserInfo
foreach (BaseUserInfo user in result.Value.data)
{
// do something with the user data
}
});
In this tutorial, you will learn how to use Party services. This guide assumes that you have already implemented the Lobby (opens new window) and Friends (opens new window) services.
Since Party implementation can vary for each game, you can familiarize yourself with other concepts and classes in the LobbyModels.cs file inside the plugin SDK.
We will start by adding simple party logic into the game.
Create a new script called PartyHandler.cs and attach it to the AccelByteHandler gameObject.
Add the following AccelByte libraries to the top of the script:
using AccelByte.Api;
using AccelByte.Models;
using AccelByte.Core;
public void CreateParty()
{
AccelBytePlugin.GetLobby().CreateParty(result =>
{
// If there is an error, display the error information
if (result.IsError)
{
Debug.Log($"Failed to create party: error code: {result.Error.Code} message: {result.Error.Message}");
}
else
{
Debug.Log("Successfully create a party");
}
});
}
If you want to save the PartyInfo of the created party, you can set the value based on result.Value.
if (result.IsError)
...
else
{
...
_partyInfo = result.Value;
}
public void InviteToParty(string inviteeUserId)
{
AccelBytePlugin.GetLobby().InviteToParty(inviteeUserId, result =>
{
// If there is an error, display the error information
if (result.IsError)
{
Debug.Log($"Failed to invite user to party: error code: {result.Error.Code} message: {result.Error.Message}");
}
else
{
Debug.Log("Successfully invite an invitee");
}
});
}
public void KickParty(string memberUserId)
{
AccelBytePlugin.GetLobby().KickPartyMember(memberUserId, result =>
{
// If there is an error, display the error information
if (result.IsError)
{
Debug.Log($"Failed to kick user from party: error code: {result.Error.Code} message: {result.Error.Message}");
}
else
{
Debug.Log($"Successfully kick member {memberUserId} from party");
}
});
}
Use this function to leave a party.
public void LeaveParty()
{
AccelBytePlugin.GetLobby().LeaveParty(result =>
{
// If there is an error, display the error information
if (result.IsError)
{
Debug.Log($"Failed to leave party: error code: {result.Error.Code} message: {result.Error.Message}");
}
else
{
Debug.Log("Successfully leave from party");
}
});
}
public void PromotePartyLeader(string memberUserId)
{
AccelBytePlugin.GetLobby().PromotePartyLeader(memberUserId, result =>
{
// If there is an error, display the error information
if (result.IsError)
{
Debug.Log($"Failed to promote member to be a party leader: error code: {result.Error.Code} message: {result.Error.Message}");
}
else
{
Debug.Log("Successfully promote member to be a party leader");
}
});
}
using AccelByte.Api;
using AccelByte.Models;
This script will hold functions that handle the Party Invitation’s related events. You can attach this in your Party Invitation prefab later on.
public void JoinParty(PartyInvitation partyInvitation)
{
AccelBytePlugin.GetLobby().JoinParty(partyInvitation.partyID, partyInvitation.invitationToken, result =>
{
// If there is an error, display the error information
if (result.IsError)
{
Debug.Log($"Failed to join party: error code: {result.Error.Code} message: {result.Error.Message}");
}
else
{
Debug.Log("Successfully join the party");
}
});
}
public void RejectPartyInvitation(PartyInvitation partyInvitation)
{
AccelBytePlugin.GetLobby().RejectPartyInvitation(partyInvitation.partyID, partyInvitation.invitationToken, result =>
{
// If there is an error, display the error information
if (result.IsError)
{
Debug.Log($"Failed to reject party invitation: error code: {result.Error.Code} message: {result.Error.Message}");
}
else
{
Debug.Log("Successfully reject the party invitation");
}
});
}
You can use the result value from the AccelBytePlugin.GetLobby().InvitedToParty event for this PartyInvitation value.
AccelBytePlugin.GetLobby().InvitedToParty += result => {};
AccelBytePlugin.GetLobby().JoinedParty += result => {};
AccelBytePlugin.GetLobby().KickedFromParty += result =>{};
AccelBytePlugin.GetLobby().LeaveFromParty += result =>{};
AccelBytePlugin.GetLobby().RejectedPartyInvitation += result =>{};
You can find these in LobbyHandler.cs under the ConnectToLobby() function. For now, we will just add a Debug.Log for each event.
_lobby.InvitedToParty += result =>{ Debug.Log($"Invited by: {result.Value.from}");}
_lobby.JoinedParty += result =>{ Debug.Log("Invitee join a party");}
_lobby.KickedFromParty += result =>{ Debug.Log("You're kicked from party");}
_lobby.LeaveFromParty += result =>{ Debug.Log($"{result.Value.userID} leave the party");}
_lobby.RejectedPartyInvitation += result =>{ Debug.Log("Invitee rejected a party invitation");}
If you want to retrieve Party data every time the data is updated, use this event:
AccelBytePlugin.GetLobby().PartyDataUpdateNotif += result =>{}
This event will return a result with the class type PartyDataUpdateNotif which contains Party data such as PartyInfo. PartyDataUpdateNotif does not have an invitationToken, but does have updatedAt which indicates when the Party data is updated, and custom_attribute which is a Dictionary that you can use with any custom info.
As with the last step, you can find this event in LobbyHandler.cs under the ConnectToLobby() function. In this case, since we only need to display Party data, just add a Debug.Log to notify the party member’s UserID via the Console output.
_lobby.PartyDataUpdateNotif += result =>{ Debug.Log($"Current Party Members: {result.Value.members}");}
You can also retrieve Party data using the GetPartyInfo() function. The PartyInfo class contains Party data such as the partyID, leaderID, members (userID), invitees (userID), and an invitationToken. To get this PartyInfo, use the following function:
AccelBytePlugin.GetLobby().GetPartyInfo(result =>
{
// If there is an error, display the error information
if (result.IsError)
{
Debug.Log($"Failed to leave party: error code: {result.Error.Code} message: {result.Error.Message}");
}
else
{
Debug.Log("Successfully leave from party");
}
});
This function returns a result with the class type PartyInfo, and you can access its values with result.Value.<the object you need>
. For example, if you want to retrieve the partyID, use result.Value.partyId.
TIP
You can only retrieve UserID from PartyDataUpdateNotif and PartyInfo, so you will need to use the GetUser() function to retrieve user data.
AccelBytePlugin.GetUser().BulkGetUserInfo(usersIdList, result => {
// Loop the result's Users Data, return in BaseUserInfo
foreach (BaseUserInfo user in result.Value.data)
{
Debug.Log($"User data: {user.displayName}");
}
});
AccelBytePlugin.GetUser().GetUserByUserId(userId, result => {
Debug.Log($"User data: {result.Value}");
});
Depending on the situation, when displaying Party data, you may want to use BulkGetUserInfo() which also contains avatarUrl.
Congratulations! You have successfully learnt how to use the Party service!
Continue on for a step by step example of the UI and code implementation. Otherwise, you are now ready to move on to Matchmaking (opens new window).
The Log Message Display prefab will spawn if a log message is created. Create a new panel, ensure it has a Log Message text, and link it under the Scroll View’s content.
Now that you have some basic Party functionalities, you can implement these into your UI.
using UnityEngine.UI;
[SerializeField]
private GameObject LobbyWindow;
[SerializeField]
private Transform canvasTransform;
[SerializeField]
private Transform partyDisplayPanel;
[SerializeField]
private GameObject partyInvitationPrefab;
#region Buttons
[SerializeField]
private Button friendsManagementButton;
[SerializeField]
private Button createPartyButton;
[SerializeField]
private Button leavePartyButton;
[SerializeField]
private Button exitButton;
#endregion
[SerializeField]
private Text partyIdText;
public Dictionary<string, string> partyMembers { private set; get; }
#region ExitMode
public enum ExitMode
{
Menu,
Lobby
}
private ExitMode ExitScreen
{
get => ExitScreen;
set
{
switch (value)
{
case ExitMode.Menu:
FriendsManagementWindow.SetActive(false);
GetComponent<MenuHandler>().Menu.gameObject.SetActive(true);
break;
case ExitMode.Lobby:
FriendsManagementWindow.SetActive(false);
GetComponent<LobbyHandler>().LobbyWindow.SetActive(true);
break;
}
}
}
#endregion
private bool isInitialized = false;
...
public void Setup(ExitMode exitType)
{
// reset the exit button's listener, then add the listener based on the exit screen type
exitButton.onClick.RemoveAllListeners();
exitButton.onClick.AddListener(() => ExitScreen = exitType);
// Check whether the FriendsPanel already set up or not
if (isInitialized)
{
DisplayMode = FriendsMode.Default;
return;
}
// Run the setup if it still hasn't
else
{
isInitialized = true;
DisplayMode = FriendsMode.Friends;
// reset listenera, so it won't triggered more than once
friendsTabButton.onClick.RemoveAllListeners();
pendingTabButton.onClick.RemoveAllListeners();
blockedTabButton.onClick.RemoveAllListeners();
// add the listeners
friendsTabButton.onClick.AddListener(() => DisplayMode = FriendsMode.Friends);
...
friendsSearchButton.onClick.AddListener(() => friendsSearchPanel.gameObject.SetActive(true));
}
}
/// Setup Party UI in Lobby and prepare State
public void SetupParty()
{
friendsManagementButton.onClick.AddListener(() =>
{
GetComponent<FriendsManagementHandler>().Setup(FriendsManagementHandler.ExitMode.Lobby);
LobbyWindow.SetActive(false);
GetComponent<FriendsManagementHandler>().FriendsManagementWindow.SetActive(true);
});
createPartyButton.onClick.AddListener(() => { CreateParty(); });
leavePartyButton.onClick.AddListener(() => { LeaveParty(); });
exitButton.onClick.AddListener(() =>
{
LobbyWindow.SetActive(false);
GetComponent<MenuHandler>().Menu.gameObject.SetActive(true);
});
}
public Button LobbyButton;
public void Create()
{
LobbyButton.onClick.AddListener(() =>
{
GetComponent<PartyHandler>().SetupParty();
Menu.gameObject.SetActive(false);
GetComponent<LobbyHandler>().LobbyWindow.SetActive(true);
});
FriendsButton.onClick.AddListener(() =>
{
GetComponent<FriendsManagementHandler>().Setup(FriendsManagementHandler.ExitMode.Menu);
...
});
}
public void SetupButton()
{
inviteToPartyButton.onClick.AddListener(() =>
{
LobbyHandler.Instance.GetComponent<PartyHandler>().InviteToParty(_userData.userId);
});
...
}
private void CreateFriendUI(PublicUserData userData)
{
FriendStatusPanel panel = Instantiate(friendsDisplayPrefab, friendsDisplayPanel).GetComponent<FriendStatusPanel>();
...
// set up the any FriendStatusPanel's related button
panel.SetupButton();
}
// add some UI references
[SerializeField]
private GameObject invitationPopUp;
[SerializeField]
private Text invitationText;
[SerializeField]
private Button acceptInvitationButton;
[SerializeField]
private Button rejectInvitationButton;
// create a function to setup the Popup and its listener
public void Setup(PartyInvitation partyInvitation)
{
AccelBytePlugin.GetUser().GetUserByUserId(partyInvitation.from, result =>
{
invitationText.text = result.Value.displayName + " invite you to join their party\nAccept invitation?";
});
acceptInvitationButton.onClick.AddListener(() => { JoinParty(partyInvitation);});
rejectInvitationButton.onClick.AddListener(() => { RejectPartyInvitation(partyInvitation);});
}
public void JoinParty(PartyInvitation partyInvitation)
{
...
// Destroy the PopUp prefab
Destroy(invitationPopUp);
}
public void RejectPartyInvitation(PartyInvitation partyInvitation)
{
...
// Destroy the PopUp prefab
Destroy(invitationPopUp);
}
/// Display all Party Data to PartyList UI
public void DisplayPartyData(Result<PartyDataUpdateNotif> partyDataNotifResult)
{
// update PartyID in UI
partyIdText.text = "PartyID: " + partyDataNotifResult.Value.partyId;
// Get all party members data based on _partyUserIds, then update data to UI
AccelBytePlugin.GetUser().BulkGetUserInfo(partyDataNotifResult.Value.members, result =>
{
if (result.IsError)
{
Debug.Log($"Failed to get party member's data: error code: {result.Error.Code} message: {result.Error.Message}");
}
else
{
// initialize dictionary
partyMembers = new Dictionary<string, string>();
// result data's order => reversed order of _partyIserIds
int _index = result.Value.data.Length;
foreach (BaseUserInfo user in result.Value.data)
{
_index -= 1;
// get transform of PlayerEntryDisplay, which is child of PartyListPanel
Transform playerEntryDisplay = partyDisplayPanel.GetChild(_index).transform;
if (user.userId == partyDataNotifResult.Value.leader)
{
// set LeaderStatusIndicator as active
Transform leaderStatusIndicator = playerEntryDisplay.GetChild(0).transform;
leaderStatusIndicator.gameObject.SetActive(true);
}
else
{
if (AccelBytePlugin.GetUser().Session.UserId == partyDataNotifResult.Value.leader)
{
// set PartyLeaderButton (promote button) as active, then add listener when onclick button
Transform partyLeaderButton = playerEntryDisplay.GetChild(1).transform;
partyLeaderButton.gameObject.SetActive(true);
partyLeaderButton.GetComponent<Button>().onClick.AddListener(() =>
{
PromotePartyLeader(user.userId);
});
// set KickPartyButton as active, then add listener when onclick button
Transform kickPartyButton = playerEntryDisplay.GetChild(2).transform;
kickPartyButton.gameObject.SetActive(true);
kickPartyButton.GetComponent<Button>().onClick.AddListener(() =>
{
KickParty(user.userId);
});
}
}
// set DisplayNameText as active, then change text to User's Display Name
Transform displayNameText = playerEntryDisplay.GetChild(3).transform;
displayNameText.gameObject.SetActive(true);
displayNameText.GetComponent<Text>().text = user.displayName;
partyMembers.Add(user.userId, user.displayName);
}
}
});
}
private void Start()
{
if (AccelBytePlugin.GetLobby().IsConnected)
{
AccelBytePlugin.GetLobby().GetPartyInfo(partyInfoResult =>
{
// update PartyID in UI
partyIdText.text = "PartyID: " + partyInfoResult.Value.partyID;
ResetPlayerEntryUI();
// Get all party members data based on _partyUserIds, then update data to UI
AccelBytePlugin.GetUser().BulkGetUserInfo(partyInfoResult.Value.members, result =>
{
if (result.IsError)
{
Debug.Log($"Failed to get party member's data: error code: {result.Error.Code} message: {result.Error.Message}");
}
else
{
// initialize dictionary
partyMembers = new Dictionary<string, string>();
// result data's order => reversed order of _partyIserIds
int _index = result.Value.data.Length;
foreach (BaseUserInfo user in result.Value.data)
{
_index -= 1;
// get transform of PlayerEntryDisplay, which is child of PartyListPanel
Transform playerEntryDisplay = partyDisplayPanel.GetChild(_index).transform;
if (user.userId == partyInfoResult.Value.leaderID)
{
// set LeaderStatusIndicator as active
Transform leaderStatusIndicator = playerEntryDisplay.GetChild(0).transform;
leaderStatusIndicator.gameObject.SetActive(true);
}
else
{
if (AccelBytePlugin.GetUser().Session.UserId == partyInfoResult.Value.leaderID)
{
// set PartyLeaderButton (promote button) as active, then add listener when onclick button
Transform partyLeaderButton = playerEntryDisplay.GetChild(1).transform;
partyLeaderButton.gameObject.SetActive(true);
partyLeaderButton.GetComponent<Button>().onClick.AddListener(() =>
{
PromotePartyLeader(user.userId);
});
// set KickPartyButton as active, then add listener when onclick button
Transform kickPartyButton = playerEntryDisplay.GetChild(2).transform;
kickPartyButton.gameObject.SetActive(true);
kickPartyButton.GetComponent<Button>().onClick.AddListener(() =>
{
KickParty(user.userId);
});
}
}
// set DisplayNameText as active, then change text to User's Display Name
Transform displayNameText = playerEntryDisplay.GetChild(3).transform;
displayNameText.gameObject.SetActive(true);
displayNameText.GetComponent<Text>().text = user.displayName;
partyMembers.Add(user.userId, user.displayName);
}
}
});
});
}
}
/// reset Party ID's UI
public void ResetPartyId()
{
partyIdText.text = "PartyID: ###############################";
partyMembers = null;
}
/// Reset Party List's UI
public void ResetPlayerEntryUI()
{
foreach(Transform playerEntryDisplay in partyDisplayPanel)
{
// set LeaderStatusIndicator as not active
Transform leaderStatusIndicator = playerEntryDisplay.GetChild(0).transform;
leaderStatusIndicator.gameObject.SetActive(false);
// set PartyLeaderButton (promote button) as not active, then remove all listener on button
Transform partyLeaderButton = playerEntryDisplay.GetChild(1).transform;
partyLeaderButton.gameObject.SetActive(false);
partyLeaderButton.GetComponent<Button>().onClick.RemoveAllListeners();
// set KickPartyButton as not active, then remove all listener on button
Transform kickPartyButton = playerEntryDisplay.GetChild(2).transform;
kickPartyButton.gameObject.SetActive(false);
kickPartyButton.GetComponent<Button>().onClick.RemoveAllListeners();
// set DisplayNameText as not active and set value to default text
Transform displayNameText = playerEntryDisplay.GetChild(3).transform;
displayNameText.gameObject.SetActive(false);
displayNameText.GetComponent<Text>().text = "PlayerUsername";
}
}
public void LeaveParty()
{
AccelBytePlugin.GetLobby().LeaveParty(result =>
{
if (result.IsError)
...
else
{
...
// reset all Party-related UIs
ResetPartyId();
ResetPlayerEntryUI();
}
});
}
public void DisplayPartyData(Result<PartyDataUpdateNotif> partyDataNotifResult)
{
// update PartyID in UI
...
// reset the all the Party List's UI
ResetPlayerEntryUI();
...
}
using UnityEngine;
using UnityEngine.UI;
public class LogMessagePanel : MonoBehaviour
{
[SerializeField]
private Text messageText;
/// Update Notification Message's UI
public void UpdateNotificationUI(string text, Color color)
{
messageText.text = text;
messageText.color = color;
}
}
public GameObject LobbyWindow;
#region Notification Box
[Header("Notification Box")]
[SerializeField]
private Transform notificationBoxContentView;
[SerializeField]
private GameObject logMessagePrefab;
#endregion
/// Write the log message on the notification box
public void WriteLogMessage(string text, Color color)
{
LogMessagePanel logPanel = Instantiate(logMessagePrefab, notificationBoxContentView).GetComponent<LogMessagePanel>();
logPanel.UpdateNotificationUI(text, color);
}
/// Called on update when received a party invitation
public void InvitePartyNotification(PartyInvitation partyInvitation)
{
Debug.Log($"Invited by: {partyInvitation.from}");
PartyInvitationPanel invitationPanel = Instantiate(partyInvitationPrefab, canvasTransform).GetComponent<PartyInvitationPanel>();
invitationPanel.Setup(partyInvitation);
}
/// Called on update when kicked from party
public void KickPartyNotification()
{
Debug.Log("You're kicked from party");
ResetPartyId();
ResetPlayerEntryUI();
}
/// Called on update when friend joined the party
public void JoinedPartyNotification(JoinNotification joinNotification)
{
Debug.Log("Invitee join a party");
AccelBytePlugin.GetUser().GetUserByUserId(joinNotification.userID, result =>
{
if (result.IsError)
{
Debug.Log($"Failed to get user data: error code: {result.Error.Code} message: {result.Error.Message}");
}
else
{
LobbyHandler.Instance.WriteLogMessage($"[Party] {result.Value.displayName} join the party", Color.black);
}
});
}
/// Called on update when friend left the party
public void LeavePartyNotification(LeaveNotification leaveNotification)
{
if (leaveNotification.userID != AccelBytePlugin.GetUser().Session.UserId)
{
Debug.Log($"{leaveNotification.userID} leave the party");
LobbyHandler.Instance.WriteLogMessage($"[Party] {partyMembers[leaveNotification.userID]} leave the party", Color.black);
}
}
public void PromotePartyLeader(string memberUserId)
{
// Instantiate the notification message
NotificationMessagePanel notificationPanel = Instantiate(notificationMessagePrefab, notificationContentView).GetComponent<NotificationMessagePanel>();
AccelBytePlugin.GetLobby().PromotePartyLeader(memberUserId, result =>
{
if (result.IsError)
{
...
// update the messageText that failed to promote leader
LobbyHandler.Instance.WriteLogMessage($"[Party] Failed to promote {partyMembers[memberUserId]} to be party leader", Color.black);
}
else
{
...
// update the messageText that success to promote leader
LobbyHandler.Instance.WriteLogMessage($"[Party] Successfully promote {partyMembers[memberUserId]} to be party leader", Color.black);
}
});
}
// Collection of party notifications
#region Party
/// Called when user gets party invitation
public void OnInvitedToParty(Result<PartyInvitation> result)
{
GetComponent<PartyHandler>().InvitePartyNotification(result.Value);
}
/// Called when user joins to the party
public void OnJoinedParty(Result<JoinNotification> result)
{
GetComponent<PartyHandler>().JoinedPartyNotification(result.Value);
}
/// Called when user is kicked by party leader
public void OnKickedFromParty(Result<KickNotification> result)
{
GetComponent<PartyHandler>().KickPartyNotification();
}
/// Called when user leaves from the party
public void OnLeaveFromParty(Result<LeaveNotification> result)
{
GetComponent<PartyHandler>().LeavePartyNotification(result.Value);
}
/// Called when user rejects party invitation
public void OnRejectedPartyInvitation(Result<PartyRejectNotif> result)
{
Debug.Log("[Party-Notification] Invitee rejected a party invitation");
}
/// Called when party data is updated
public void OnPartyDataUpdateNotif(Result<PartyDataUpdateNotif> result)
{
GetComponent<PartyHandler>().DisplayPartyData(result);
}
#endregion
public void ConnectToLobby()
{
...
//Party
_lobby.InvitedToParty += notificationHandler.OnInvitedToParty;
_lobby.JoinedParty += notificationHandler.OnJoinedParty;
_lobby.KickedFromParty += notificationHandler.OnKickedFromParty;
_lobby.LeaveFromParty += notificationHandler.OnLeaveFromParty;
_lobby.RejectedPartyInvitation += notificationHandler.OnRejectedPartyInvitation;
_lobby.PartyDataUpdateNotif += notificationHandler.OnPartyDataUpdateNotif;
...
}
public void RemoveLobbyListeners()
{
...
//Party
_lobby.InvitedToParty -= notificationHandler.OnInvitedToParty;
_lobby.JoinedParty -= notificationHandler.OnJoinedParty;
_lobby.KickedFromParty -= notificationHandler.OnKickedFromParty;
_lobby.LeaveFromParty -= notificationHandler.OnLeaveFromParty;
_lobby.RejectedPartyInvitation -= notificationHandler.OnRejectedPartyInvitation;
_lobby.PartyDataUpdateNotif -= notificationHandler.OnPartyDataUpdateNotif;
}
Congratulations! You have now fully implemented the Party service.
Proceed to the next section to learn how to implement Matchmaking (opens new window).
// Copyright (c) 2021 - 2022 AccelByte Inc. All Rights Reserved.
// This is licensed software from AccelByte Inc, for limitations
// and restrictions contact your company contract manager.
using AccelByte.Api;
using AccelByte.Core;
using AccelByte.Models;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class PartyHandler : MonoBehaviour
{
[SerializeField]
private GameObject LobbyWindow;
[SerializeField]
private Transform canvasTransform;
[SerializeField]
private Transform partyDisplayPanel;
[SerializeField]
private GameObject partyInvitationPrefab;
#region Buttons
[SerializeField]
private Button friendsManagementButton;
[SerializeField]
private Button createPartyButton;
[SerializeField]
private Button leavePartyButton;
[SerializeField]
private Button exitButton;
#endregion
[SerializeField]
private Text partyIdText;
public Dictionary<string, string> partyMembers { private set; get; }
private void Start()
{
if (AccelBytePlugin.GetLobby().IsConnected)
{
AccelBytePlugin.GetLobby().GetPartyInfo(partyInfoResult =>
{
// update PartyID in UI
partyIdText.text = "PartyID: " + partyInfoResult.Value.partyID;
ResetPlayerEntryUI();
// Get all party members data based on _partyUserIds, then update data to UI
AccelBytePlugin.GetUser().BulkGetUserInfo(partyInfoResult.Value.members, result =>
{
if (result.IsError)
{
Debug.Log($"Failed to get party member's data: error code: {result.Error.Code} message: {result.Error.Message}");
}
else
{
// initialize dictionary
partyMembers = new Dictionary<string, string>();
// result data's order => reversed order of _partyIserIds
int _index = result.Value.data.Length;
foreach (BaseUserInfo user in result.Value.data)
{
_index -= 1;
// get transform of PlayerEntryDisplay, which is child of PartyListPanel
Transform playerEntryDisplay = partyDisplayPanel.GetChild(_index).transform;
if (user.userId == partyInfoResult.Value.leaderID)
{
// set LeaderStatusIndicator as active
Transform leaderStatusIndicator = playerEntryDisplay.GetChild(0).transform;
leaderStatusIndicator.gameObject.SetActive(true);
}
else
{
if (AccelBytePlugin.GetUser().Session.UserId == partyInfoResult.Value.leaderID)
{
// set PartyLeaderButton (promote button) as active, then add listener when onclick button
Transform partyLeaderButton = playerEntryDisplay.GetChild(1).transform;
partyLeaderButton.gameObject.SetActive(true);
partyLeaderButton.GetComponent<Button>().onClick.AddListener(() =>
{
PromotePartyLeader(user.userId);
});
// set KickPartyButton as active, then add listener when onclick button
Transform kickPartyButton = playerEntryDisplay.GetChild(2).transform;
kickPartyButton.gameObject.SetActive(true);
kickPartyButton.GetComponent<Button>().onClick.AddListener(() =>
{
KickParty(user.userId);
});
}
}
// set DisplayNameText as active, then change text to User's Display Name
Transform displayNameText = playerEntryDisplay.GetChild(3).transform;
displayNameText.gameObject.SetActive(true);
displayNameText.GetComponent<Text>().text = user.displayName;
partyMembers.Add(user.userId, user.displayName);
}
}
});
});
}
}
/// <summary>
/// Setup Party UI in Lobby and prepare State
/// </summary>
public void SetupParty()
{
friendsManagementButton.onClick.AddListener(() =>
{
GetComponent<FriendsManagementHandler>().Setup(FriendsManagementHandler.ExitMode.Lobby);
LobbyWindow.SetActive(false);
GetComponent<FriendsManagementHandler>().FriendsManagementWindow.SetActive(true);
});
createPartyButton.onClick.AddListener(() => { CreateParty(); });
leavePartyButton.onClick.AddListener(() => { LeaveParty(); });
exitButton.onClick.AddListener(() =>
{
LobbyWindow.SetActive(false);
GetComponent<MenuHandler>().Menu.gameObject.SetActive(true);
});
}
/// <summary>
/// Create party and update partyID to UI
/// </summary>
public void CreateParty()
{
AccelBytePlugin.GetLobby().CreateParty(result =>
{
if (result.IsError)
{
Debug.Log($"Failed to create party: error code: {result.Error.Code} message: {result.Error.Message}");
}
else
{
Debug.Log("Successfully create a party");
}
});
}
/// <summary>
/// Invite friend to party
/// </summary>
/// <param name="inviteeUserId"> userId of the user that will received the invitation</param>
public void InviteToParty(string inviteeUserId)
{
AccelBytePlugin.GetLobby().InviteToParty(inviteeUserId, result =>
{
if (result.IsError)
{
Debug.Log($"Failed to invite user to party: error code: {result.Error.Code} message: {result.Error.Message}");
}
else
{
Debug.Log("Successfully invite an invitee");
}
});
}
/// <summary>
/// Kick user from party
/// </summary>
/// <param name="memberUserId"> userId of the member that will be kicked from the party</param>
public void KickParty(string memberUserId)
{
AccelBytePlugin.GetLobby().KickPartyMember(memberUserId, result =>
{
if (result.IsError)
{
Debug.Log($"Failed to kick user from party: error code: {result.Error.Code} message: {result.Error.Message}");
}
else
{
Debug.Log($"Successfully kick member {memberUserId} from party");
}
});
}
/// <summary>
/// Leave from party
/// </summary>
public void LeaveParty()
{
AccelBytePlugin.GetLobby().LeaveParty(result =>
{
if (result.IsError)
{
Debug.Log($"Failed to leave party: error code: {result.Error.Code} message: {result.Error.Message}");
}
else
{
Debug.Log("Successfully leave from party");
ResetPartyId();
ResetPlayerEntryUI();
}
});
}
/// <summary>
/// Promote member to be a party leader
/// </summary>
/// <param name="memberUserId"> userId of the member that will be promoted as party leader</param>
public void PromotePartyLeader(string memberUserId)
{
AccelBytePlugin.GetLobby().PromotePartyLeader(memberUserId, result =>
{
if (result.IsError)
{
Debug.Log($"Failed to promote member to be party leader: error code: {result.Error.Code} message: {result.Error.Message}");
LobbyHandler.Instance.WriteLogMessage($"[Party] Failed to promote {partyMembers[memberUserId]} to be party leader", Color.black);
}
else
{
Debug.Log("Successfully promote member to be a party leader");
LobbyHandler.Instance.WriteLogMessage($"[Party] Successfully promote {partyMembers[memberUserId]} to be party leader", Color.black);
}
});
}
/// <summary>
/// Display all Party Data to PartyList UI
/// </summary>
/// <param name="partyDataNotifResult"> </param>
public void DisplayPartyData(Result<PartyDataUpdateNotif> partyDataNotifResult)
{
// update PartyID in UI
partyIdText.text = "PartyID: " + partyDataNotifResult.Value.partyId;
ResetPlayerEntryUI();
// Get all party members data based on _partyUserIds, then update data to UI
AccelBytePlugin.GetUser().BulkGetUserInfo(partyDataNotifResult.Value.members, result =>
{
if (result.IsError)
{
Debug.Log($"Failed to get party member's data: error code: {result.Error.Code} message: {result.Error.Message}");
}
else
{
// initialize dictionary
partyMembers = new Dictionary<string, string>();
// result data's order => reversed order of _partyIserIds
int _index = result.Value.data.Length;
foreach (BaseUserInfo user in result.Value.data)
{
_index -= 1;
// get transform of PlayerEntryDisplay, which is child of PartyListPanel
Transform playerEntryDisplay = partyDisplayPanel.GetChild(_index).transform;
if (user.userId == partyDataNotifResult.Value.leader)
{
// set LeaderStatusIndicator as active
Transform leaderStatusIndicator = playerEntryDisplay.GetChild(0).transform;
leaderStatusIndicator.gameObject.SetActive(true);
}
else
{
if (AccelBytePlugin.GetUser().Session.UserId == partyDataNotifResult.Value.leader)
{
// set PartyLeaderButton (promote button) as active, then add listener when onclick button
Transform partyLeaderButton = playerEntryDisplay.GetChild(1).transform;
partyLeaderButton.gameObject.SetActive(true);
partyLeaderButton.GetComponent<Button>().onClick.AddListener(() =>
{
PromotePartyLeader(user.userId);
});
// set KickPartyButton as active, then add listener when onclick button
Transform kickPartyButton = playerEntryDisplay.GetChild(2).transform;
kickPartyButton.gameObject.SetActive(true);
kickPartyButton.GetComponent<Button>().onClick.AddListener(() =>
{
KickParty(user.userId);
});
}
}
// set DisplayNameText as active, then change text to User's Display Name
Transform displayNameText = playerEntryDisplay.GetChild(3).transform;
displayNameText.gameObject.SetActive(true);
displayNameText.GetComponent<Text>().text = user.displayName;
partyMembers.Add(user.userId, user.displayName);
}
}
});
}
/// <summary>
/// reset Party ID's UI
/// </summary>
public void ResetPartyId()
{
partyIdText.text = "PartyID: ###############################";
partyMembers = null;
}
/// <summary>
/// Reset Party List's UI
/// </summary>
public void ResetPlayerEntryUI()
{
foreach(Transform playerEntryDisplay in partyDisplayPanel)
{
// set LeaderStatusIndicator as not active
Transform leaderStatusIndicator = playerEntryDisplay.GetChild(0).transform;
leaderStatusIndicator.gameObject.SetActive(false);
// set PartyLeaderButton (promote button) as not active, then remove all listener on button
Transform partyLeaderButton = playerEntryDisplay.GetChild(1).transform;
partyLeaderButton.gameObject.SetActive(false);
partyLeaderButton.GetComponent<Button>().onClick.RemoveAllListeners();
// set KickPartyButton as not active, then remove all listener on button
Transform kickPartyButton = playerEntryDisplay.GetChild(2).transform;
kickPartyButton.gameObject.SetActive(false);
kickPartyButton.GetComponent<Button>().onClick.RemoveAllListeners();
// set DisplayNameText as not active and set value to default text
Transform displayNameText = playerEntryDisplay.GetChild(3).transform;
displayNameText.gameObject.SetActive(false);
displayNameText.GetComponent<Text>().text = "PlayerUsername";
}
}
/// <summary>
/// Called on update when received a party invitation
/// </summary>
/// <param name="partyInvitation"> contains Party Invitation's data, consists of sender's userId, partyId, and invitationToken</param>
public void InvitePartyNotification(PartyInvitation partyInvitation)
{
Debug.Log($"[Party-Notification] Invited by: {partyInvitation.from}");
PartyInvitationPanel invitationPanel = Instantiate(partyInvitationPrefab, canvasTransform).GetComponent<PartyInvitationPanel>();
invitationPanel.Setup(partyInvitation);
}
/// <summary>
/// Called on update when kicked from party
/// </summary>
public void KickPartyNotification()
{
Debug.Log("[Party-Notification] You're kicked from party");
ResetPartyId();
ResetPlayerEntryUI();
}
/// <summary>
/// Called on update when friend joined the party
/// </summary>
/// <param name="joinNotification"> contains data of the user who just joined the party, consists of user's userId</param>
public void JoinedPartyNotification(JoinNotification joinNotification)
{
Debug.Log("[Party-Notification] Invitee join a party");
AccelBytePlugin.GetUser().GetUserByUserId(joinNotification.userID, result =>
{
if (result.IsError)
{
Debug.Log($"Failed to get user data: error code: {result.Error.Code} message: {result.Error.Message}");
}
else
{
LobbyHandler.Instance.WriteLogMessage($"[Party] {result.Value.displayName} join the party", Color.black);
}
});
}
/// <summary>
/// Called on update when friend left the party
/// </summary>
/// <param name="leaveNotification"> contains userId's data of the user who just left and the party leader's userId</param>
public void LeavePartyNotification(LeaveNotification leaveNotification)
{
if (leaveNotification.userID != AccelBytePlugin.GetUser().Session.UserId)
{
Debug.Log($"{leaveNotification.userID} leave the party");
LobbyHandler.Instance.WriteLogMessage($"{partyMembers[leaveNotification.userID]} leave the party", Color.black);
}
}
}
// Copyright (c) 2021 - 2022 AccelByte Inc. All Rights Reserved.
// This is licensed software from AccelByte Inc, for limitations
// and restrictions contact your company contract manager.
using AccelByte.Api;
using AccelByte.Models;
using UnityEngine;
using UnityEngine.UI;
public class PartyInvitationPanel : MonoBehaviour
{
[SerializeField]
private GameObject invitationPopUp;
[SerializeField]
private Text invitationText;
[SerializeField]
private Button acceptInvitationButton;
[SerializeField]
private Button rejectInvitationButton;
/// <summary>
/// Setup PartyInvitation's Popup UI and event listener
/// </summary>
public void Setup(PartyInvitation partyInvitation)
{
AccelBytePlugin.GetUser().GetUserByUserId(partyInvitation.from, result =>
{
invitationText.text = result.Value.displayName + " invite you to join their party\nAccept invitation?";
});
acceptInvitationButton.onClick.AddListener(() => { JoinParty(partyInvitation);});
rejectInvitationButton.onClick.AddListener(() => { RejectPartyInvitation(partyInvitation);});
}
/// <summary>
/// Accept the invitation and join the party
/// </summary>
public void JoinParty(PartyInvitation partyInvitation)
{
AccelBytePlugin.GetLobby().JoinParty(partyInvitation.partyID, partyInvitation.invitationToken, result =>
{
if (result.IsError)
{
Debug.Log($"Failed to join party: error code: {result.Error.Code} message: {result.Error.Message}");
}
else
{
Debug.Log("Successfully join a party");
}
});
Destroy(invitationPopUp);
}
/// <summary>
/// Reject the party invitation
/// </summary>
public void RejectPartyInvitation(PartyInvitation partyInvitation)
{
AccelBytePlugin.GetLobby().RejectPartyInvitation(partyInvitation.partyID, partyInvitation.invitationToken, result =>
{
if (result.IsError)
{
Debug.Log($"Failed to reject party invitation: error code: {result.Error.Code} message: {result.Error.Message}");
}
else
{
Debug.Log("Successfully reject a party invitation");
}
});
Destroy(invitationPopUp);
}
}
// Copyright (c) 2021 - 2022 AccelByte Inc. All Rights Reserved.
// This is licensed software from AccelByte Inc, for limitations
// and restrictions contact your company contract manager.
using AccelByte.Api;
using AccelByte.Models;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class LogMessagePanel : MonoBehaviour
{
[SerializeField]
private Text messageText;
/// <summary>
/// Update Notification Message's UI
/// </summary>
/// <param name="text"> text that will be shown in the party notification</param>
public void UpdateNotificationUI(string text, Color color)
{
messageText.text = text;
messageText.color = color;
}
}
// Copyright (c) 2021 - 2022 AccelByte Inc. All Rights Reserved.
// This is licensed software from AccelByte Inc, for limitations
// and restrictions contact your company contract manager.
using UnityEngine;
using AccelByte.Api;
public class LobbyHandler : MonoBehaviour
{
/// <summary>
/// Private Instance
/// </summary>
static LobbyHandler _instance;
/// <summary>
/// The Instance Getter
/// </summary>
public static LobbyHandler Instance => _instance;
/// <summary>
/// The Instance Getter
/// </summary>
private Lobby _lobby;
public GameObject LobbyWindow;
#region Notification Box
[Header("Notification Box")]
[SerializeField]
private Transform notificationBoxContentView;
[SerializeField]
private GameObject logMessagePrefab;
#endregion
[HideInInspector]
public NotificationHandler notificationHandler;
private void Awake()
{
// Check if another Instance is already created, and if so delete this one, otherwise destroy the object
if (_instance != null && _instance != this)
{
Destroy(this);
return;
}
else
{
_instance = this;
}
// Get the the object handler
notificationHandler = gameObject.GetComponent<NotificationHandler>();
}
/// <summary>
/// Connect to the <see cref="Lobby"/> and setup CallBacks
/// </summary>
public void ConnectToLobby()
{
//Get a reference to the instance of the Lobby
_lobby = AccelBytePlugin.GetLobby();
//Init menu handler
GetComponent<MenuHandler>().Create();
GetComponent<MenuHandler>().Menu.gameObject.SetActive(true);
//Connection
_lobby.Connected += notificationHandler.OnConnected;
_lobby.Disconnecting += notificationHandler.OnDisconnecting;
_lobby.Disconnected += notificationHandler.OnDisconnected;
//Friends
_lobby.FriendsStatusChanged += notificationHandler.OnFriendsStatusChanged;
_lobby.FriendRequestAccepted += notificationHandler.OnFriendRequestAccepted;
_lobby.OnIncomingFriendRequest += notificationHandler.OnIncomingFriendRequest;
_lobby.FriendRequestCanceled += notificationHandler.OnFriendRequestCanceled;
_lobby.FriendRequestRejected += notificationHandler.OnFriendRequestRejected;
_lobby.OnUnfriend += notificationHandler.OnUnfriend;
//Party
_lobby.InvitedToParty += notificationHandler.OnInvitedToParty;
_lobby.JoinedParty += notificationHandler.OnJoinedParty;
_lobby.KickedFromParty += notificationHandler.OnKickedFromParty;
_lobby.LeaveFromParty += notificationHandler.OnLeaveFromParty;
_lobby.RejectedPartyInvitation += notificationHandler.OnRejectedPartyInvitation;
_lobby.PartyDataUpdateNotif += notificationHandler.OnPartyDataUpdateNotif;
//Connect to the Lobby
if (!_lobby.IsConnected)
{
_lobby.Connect();
}
}
public void RemoveLobbyListeners()
{
//Remove delegate from Lobby
//Connection
_lobby.Connected -= notificationHandler.OnConnected;
_lobby.Disconnecting -= notificationHandler.OnDisconnecting;
_lobby.Disconnected -= notificationHandler.OnDisconnected;
//Friends
_lobby.FriendsStatusChanged -= notificationHandler.OnFriendsStatusChanged;
_lobby.FriendRequestAccepted -= notificationHandler.OnFriendRequestAccepted;
_lobby.OnIncomingFriendRequest -= notificationHandler.OnIncomingFriendRequest;
_lobby.FriendRequestCanceled -= notificationHandler.OnFriendRequestCanceled;
_lobby.FriendRequestRejected -= notificationHandler.OnFriendRequestRejected;
_lobby.OnUnfriend -= notificationHandler.OnUnfriend;
//Party
_lobby.InvitedToParty -= notificationHandler.OnInvitedToParty;
_lobby.JoinedParty -= notificationHandler.OnJoinedParty;
_lobby.KickedFromParty -= notificationHandler.OnKickedFromParty;
_lobby.LeaveFromParty -= notificationHandler.OnLeaveFromParty;
_lobby.RejectedPartyInvitation -= notificationHandler.OnRejectedPartyInvitation;
_lobby.PartyDataUpdateNotif -= notificationHandler.OnPartyDataUpdateNotif;
}
public void DisconnectFromLobby()
{
if (AccelBytePlugin.GetLobby().IsConnected)
{
AccelBytePlugin.GetLobby().Disconnect();
}
}
private void OnApplicationQuit()
{
// Attempt to Disconnect from the Lobby when the Game Quits
DisconnectFromLobby();
}
/// <summary>
/// Write the log message on the notification box
/// </summary>
/// <param name="text"> text that will be shown in the party notification</param>
public void WriteLogMessage(string text, Color color)
{
LogMessagePanel logPanel = Instantiate(logMessagePrefab, notificationBoxContentView).GetComponent<LogMessagePanel>();
logPanel.UpdateNotificationUI(text, color);
}
}
// Copyright (c) 2021 - 2022 AccelByte Inc. All Rights Reserved.
// This is licensed software from AccelByte Inc, for limitations
// and restrictions contact your company contract manager.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class MenuHandler : MonoBehaviour
{
public Transform Menu;
public Button LobbyButton;
public Button FriendsButton;
private bool isInitialized = false;
public void Create()
{
if (isInitialized) return;
isInitialized = true;
LobbyButton.onClick.AddListener(() =>
{
GetComponent<PartyHandler>().SetupParty();
Menu.gameObject.SetActive(false);
GetComponent<LobbyHandler>().LobbyWindow.SetActive(true);
});
FriendsButton.onClick.AddListener(() =>
{
GetComponent<FriendsManagementHandler>().Setup(FriendsManagementHandler.ExitMode.Menu);
Menu.gameObject.SetActive(false);
GetComponent<FriendsManagementHandler>().FriendsManagementWindow.SetActive(true);
});
}
}
// Copyright (c) 2021 - 2022 AccelByte Inc. All Rights Reserved.
// This is licensed software from AccelByte Inc, for limitations
// and restrictions contact your company contract manager.
using UnityEngine;
using AccelByte.Models;
using AccelByte.Core;
public class NotificationHandler : MonoBehaviour
{
#region Notifications
// Collection of connection notifications
#region Connections
/// <summary>
/// Called when lobby is connected
/// </summary>
public void OnConnected()
{
Debug.Log("Lobby Connected");
}
/// <summary>
/// Called when connection is disconnecting
/// </summary>
/// <param name="result"> Contains data of message</param>
public void OnDisconnecting(Result<DisconnectNotif> result)
{
Debug.Log($"Lobby Disconnecting {result.Value.message}");
}
/// <summary>
/// Called when connection is being disconnected
/// </summary>
/// <param name="result"> Contains data of websocket close code</param>
public void OnDisconnected(WsCloseCode result)
{
Debug.Log($"Lobby Disconnected: {result}");
}
#endregion
// Collection of friend notifications
#region Friends
/// <summary>
/// Called when friend status is changed
/// </summary>
/// <param name="result"> Contains data of user id, availability, status, etc</param>
public void OnFriendsStatusChanged(Result<FriendsStatusNotif> result)
{
GetComponent<FriendsManagementHandler>().UpdateFriends(result.Value);
}
/// <summary>
/// Called when friend request is accepted
/// </summary>
/// <param name="result"> Contains data of friend's user id</param>
public void OnFriendRequestAccepted(Result<Friend> result)
{
Debug.Log($"Accepted a Friend Request from user {result.Value.friendId}");
}
/// <summary>
/// Called when there is incomming friend request
/// </summary>
/// <param name="result"> Contains data of friend's user id</param>
public void OnIncomingFriendRequest(Result<Friend> result)
{
Debug.Log($"Received a Friend Request from user {result.Value.friendId}");
}
/// <summary>
/// Called when friend is unfriend
/// </summary>
/// <param name="result"> Contains data of friend's user id</param>
public void OnUnfriend(Result<Friend> result)
{
Debug.Log($"Unfriended User {result.Value.friendId}");
}
/// <summary>
/// Called when friend request is canceled
/// </summary>
/// <param name="result"> Contains data of sender user id</param>
public void OnFriendRequestCanceled(Result<Acquaintance> result)
{
Debug.Log($"Cancelled a Friend Request from user {result.Value.userId}");
}
/// <summary>
/// Called when friend request is rejected
/// </summary>
/// <param name="result"> Contains data of rejector user id</param>
public void OnFriendRequestRejected(Result<Acquaintance> result)
{
Debug.Log($"Rejected a Friend Request from user {result.Value.userId}");
}
#endregion
// Collection of party notifications
#region Party
/// <summary>
/// Called when user gets party invitation
/// </summary>
/// <param name="result"> Contains data of inviter, party id, and invitation token</param>
public void OnInvitedToParty(Result<PartyInvitation> result)
{
GetComponent<PartyHandler>().InvitePartyNotification(result.Value);
}
/// <summary>
/// Called when user joins to the party
/// </summary>
/// <param name="result"> Contains data of joined user id</param>
public void OnJoinedParty(Result<JoinNotification> result)
{
GetComponent<PartyHandler>().JoinedPartyNotification(result.Value);
}
/// <summary>
/// Called when user is kicked by party leader
/// </summary>
/// <param name="result"> Contains data of party leader's user id, party id, and kicked user id</param>
public void OnKickedFromParty(Result<KickNotification> result)
{
GetComponent<PartyHandler>().KickPartyNotification();
}
/// <summary>
/// Called when user leaves from the party
/// </summary>
/// <param name="result"> Contains data of party leader's user id and leaver user id</param>
public void OnLeaveFromParty(Result<LeaveNotification> result)
{
GetComponent<PartyHandler>().LeavePartyNotification(result.Value);
}
/// <summary>
/// Called when user rejects party invitation
/// </summary>
/// <param name="result"> Contains data of party id, party leader's user id, and rejector user id</param>
public void OnRejectedPartyInvitation(Result<PartyRejectNotif> result)
{
Debug.Log("[Party-Notification] Invitee rejected a party invitation");
}
/// <summary>
/// Called when party data is updated
/// </summary>
/// <param name="result"> Contains data of updated party</param>
public void OnPartyDataUpdateNotif(Result<PartyDataUpdateNotif> result)
{
GetComponent<PartyHandler>().DisplayPartyData(result);
}
#endregion
#endregion
}
// Copyright (c) 2021 - 2022 AccelByte Inc. All Rights Reserved.
// This is licensed software from AccelByte Inc, for limitations
// and restrictions contact your company contract manager.
using System.Collections.Generic;
using UnityEngine;
using AccelByte.Api;
using AccelByte.Models;
using UnityEngine.Serialization;
using UnityEngine.UI;
using Button = UnityEngine.UI.Button;
public class FriendsManagementHandler : MonoBehaviour
{
private Dictionary<string, FriendStatusPanel> friendUIDictionary = new Dictionary<string, FriendStatusPanel>();
[Header("Panels")]
public GameObject FriendsManagementWindow;
[FormerlySerializedAs("FriendsPanel")]
[SerializeField]
private RectTransform friendsPanel;
[SerializeField]
private RectTransform requestsPanel;
[SerializeField]
private RectTransform blockedPanel;
#region Buttons
[Header("Buttons")]
[SerializeField]
private Button friendsTabButton;
[SerializeField]
private Button pendingTabButton;
[SerializeField]
private Button blockedTabButton;
[SerializeField]
private Button exitButton;
#endregion
[Header("Friends Panel")]
[SerializeField]
private Transform friendsDisplayPanel;
[FormerlySerializedAs("FriendsDisplayPrefab")]
[SerializeField]
private GameObject friendsDisplayPrefab;
[SerializeField]
private Button friendsSearchButton;
[SerializeField]
private Transform friendsDisplayPlaceholder;
#region Search
[Header("Search Panel")]
[SerializeField]
private GameObject addFriendsPrefab;
[SerializeField]
private Transform friendsSearchPanel;
[SerializeField]
private InputField friendsSearchInputField;
[SerializeField]
private RectTransform friendsSearchScrollView;
[SerializeField]
private Button friendsSearchQuitButton;
[SerializeField]
private Transform friendsSearchPlaceholder;
#endregion
#region Pending
[Header("Pending Panel")]
[SerializeField]
private RectTransform pendingIncomingRequestsContent;
[SerializeField]
private RectTransform pendingOutgoingRequestsContent;
[SerializeField]
private GameObject pendingIncomingRequestsPrefab;
[SerializeField]
private GameObject pendingOutgoingRequestsPrefab;
[SerializeField]
private Transform pendingIncomingRequestPlaceholder;
[SerializeField]
private Transform pendingOutgoingRequestPlaceholder;
[SerializeField]
private Text pendingIncomingRequestText;
[SerializeField]
private Text pendingOutgoingRequestText;
#endregion
#region Blocked
[Header("Blocked")]
[SerializeField]
private RectTransform blockedContent;
[SerializeField]
private GameObject blockedUserPrefab;
[SerializeField]
private Transform blockedDisplayPlaceholder;
#endregion
private bool setupStatus = false;
#region FriendsMode
public enum FriendsMode
{
Default,
Friends,
Pending,
Blocked
};
private FriendsMode _displayMode = FriendsMode.Default;
private FriendsMode DisplayMode
{
get => _displayMode;
set
{
switch (value)
{
case FriendsMode.Default:
friendsPanel.gameObject.SetActive(true);
requestsPanel.gameObject.SetActive(false);
blockedPanel.gameObject.SetActive(false);
break;
case FriendsMode.Friends:
friendsPanel.gameObject.SetActive(true);
requestsPanel.gameObject.SetActive(false);
blockedPanel.gameObject.SetActive(false);
GetFriends();
break;
case FriendsMode.Pending:
requestsPanel.gameObject.SetActive(true);
friendsPanel.gameObject.SetActive(false);
blockedPanel.gameObject.SetActive(false);
DisplayPending();
break;
case FriendsMode.Blocked:
blockedPanel.gameObject.SetActive(true);
friendsPanel.gameObject.SetActive(false);
requestsPanel.gameObject.SetActive(false);
DisplayBlocked();
break;
}
}
}
#endregion
#region ExitMode
public enum ExitMode
{
Menu,
Lobby
}
private ExitMode ExitScreen
{
get => ExitScreen;
set
{
switch (value)
{
case ExitMode.Menu:
FriendsManagementWindow.SetActive(false);
GetComponent<MenuHandler>().Menu.gameObject.SetActive(true);
break;
case ExitMode.Lobby:
FriendsManagementWindow.SetActive(false);
GetComponent<LobbyHandler>().LobbyWindow.SetActive(true);
break;
}
}
}
#endregion
public void UpdateFriends(FriendsStatusNotif notification)
{
//Find the friend and update it's UI
if (friendUIDictionary.ContainsKey(notification.userID))
{
friendUIDictionary[notification.userID].SetOnlineStatus(notification);
}
//Otherwise We should handle this in some way, possibly creating a Friend UI Piece
else
{
Debug.Log("Unregistered Friend received a Notification");
}
}
/// <summary>
/// Setup UI and prepare State
/// </summary>
/// <param name="exitType"> name of the destination panel</param>
public void Setup(ExitMode exitType)
{
// reset the exit button's listener, then add the listener based on the exit screen type
exitButton.onClick.RemoveAllListeners();
exitButton.onClick.AddListener(() => ExitScreen = exitType);
// Check whether the FriendsPanel already set up or not
if (setupStatus)
{
DisplayMode = FriendsMode.Default;
return;
}
// Run the setup if it still hasn't
else
{
setupStatus = true;
DisplayMode = FriendsMode.Friends;
// reset listenera, so it won't triggered more than once
friendsTabButton.onClick.RemoveAllListeners();
pendingTabButton.onClick.RemoveAllListeners();
blockedTabButton.onClick.RemoveAllListeners();
// add the listeners
friendsTabButton.onClick.AddListener(() => DisplayMode = FriendsMode.Friends);
pendingTabButton.onClick.AddListener(() => DisplayMode = FriendsMode.Pending);
blockedTabButton.onClick.AddListener(() => DisplayMode = FriendsMode.Blocked);
friendsSearchPanel.gameObject.SetActive(false);
friendsDisplayPlaceholder.gameObject.SetActive(true);
friendsSearchQuitButton.onClick.AddListener(() => friendsSearchPanel.gameObject.SetActive(false));
friendsSearchButton.onClick.AddListener(DisplaySearch);
friendsSearchInputField.onEndEdit.AddListener(SearchForFriends);
friendsSearchButton.onClick.AddListener(() => friendsSearchPanel.gameObject.SetActive(true));
}
}
/// <summary>
/// Get Friends and Display them
/// </summary>
private void GetFriends()
{
//Cleanup First
LoopThroughTransformAndDestroy(friendsDisplayPanel.transform, friendsDisplayPlaceholder);
AccelBytePlugin.GetLobby().LoadFriendsList(result =>
{
//Check this is not an error
if (!result.IsError)
{
//Check if no friends were returned
if (result.Value.friendsId.Length <= 0)
{
//Display the Placeholder Text
friendsDisplayPlaceholder.gameObject.SetActive(true);
return;
}
//Hide the Placeholder Text
friendsDisplayPlaceholder.gameObject.SetActive(false);
//Fire off Requests to create UI for each friend
Debug.Log("Loaded Friends List Succesfully");
foreach (string friendID in result.Value.friendsId)
{
Debug.Log($"Friend : {friendID}");
AccelBytePlugin.GetUser().GetUserByUserId(friendID, x =>
{
CreateFriendUI(x.Value);
});
}
}
else
{
//Display the Placeholder
friendsDisplayPlaceholder.gameObject.SetActive(true);
Debug.LogWarning("Error in Getting Friends");
}
});
}
private void CreateFriendUI(PublicUserData userData)
{
FriendStatusPanel panel = Instantiate(friendsDisplayPrefab, friendsDisplayPanel).GetComponent<FriendStatusPanel>();
panel.Create(userData);
if (!friendUIDictionary.ContainsKey(userData.userId))
{
friendUIDictionary.Add(userData.userId, panel);
}
panel.SetupButton();
}
private void DisplaySearch()
{
friendsSearchPanel.gameObject.SetActive(true);
LoopThroughTransformAndDestroy(friendsSearchScrollView.transform, friendsSearchPlaceholder);
friendsSearchPlaceholder.gameObject.SetActive(true);
}
private void SearchForFriends(string query)
{
AccelBytePlugin.GetUser().SearchUsers(query, result =>
{
if (!result.IsError)
{
ListQueriedusers(result.Value);
}
else
{
Debug.LogWarning($"Unable to Query Users Code: {result.Error.Code}, Message: {result.Error.Message}");
}
});
}
private void ListQueriedusers(PagedPublicUsersInfo pagedInfo)
{
//Cleanup First
LoopThroughTransformAndDestroy(friendsSearchScrollView.transform, friendsSearchPlaceholder);
if (pagedInfo.data.Length <=0)
{
friendsSearchPlaceholder.gameObject.SetActive(true);
}
else
{
friendsSearchPlaceholder.gameObject.SetActive(false);
foreach (PublicUserInfo info in pagedInfo.data)
{
FriendsAddPanel addPanel = Instantiate(addFriendsPrefab,friendsSearchScrollView).GetComponent<FriendsAddPanel>();
addPanel.Create(info);
}
}
}
private void DisplayPending()
{
//Cleanup First, remove all Children from the Contents OTHER than the Placeholders
LoopThroughTransformAndDestroy(pendingIncomingRequestsContent.transform, pendingIncomingRequestPlaceholder);
LoopThroughTransformAndDestroy(pendingOutgoingRequestsContent.transform, pendingOutgoingRequestPlaceholder);
//Get all Incoming Friend Requests
AccelBytePlugin.GetLobby().ListIncomingFriends(result =>
{
//Check for an Error
if (result.IsError)
{
Debug.LogWarning($"Unable to get Incoming Requests Code: {result.Error.Code}, Message: {result.Error.Message}");
//Set the Placeholder Text to be Active so it doesn't just look broken
pendingIncomingRequestPlaceholder.gameObject.SetActive(true);
}
else
{
//If there are Zero Incoming Requests, set the PlaceHolder to be active
if (result.Value.friendsId.Length <= 0)
{
pendingIncomingRequestPlaceholder.gameObject.SetActive(true);
}
//Otherwise set the PlaceHolder to be inactive
else
{
pendingIncomingRequestPlaceholder.gameObject.SetActive(false);
}
//Loop through all the UserID's returned by the Friends callback and get their PublicUserData
foreach (string userID in result.Value.friendsId)
{
//Request the PublicUserData for the specific Friend
AccelBytePlugin.GetUser().GetUserByUserId(userID, userResult =>
{
//If it's an Error, report it and do nothing else
if (userResult.IsError)
{
Debug.LogWarning($"Unable to User Code: {userResult.Error.Code}, Message: {userResult.Error.Message}");
}
//If we have valid data, Instantiate the Prefab for the specific UI Piece and call relevant functions
else
{
FriendsIncomingPanel incomingPanel = Instantiate(pendingIncomingRequestsPrefab, pendingIncomingRequestsContent).GetComponent<FriendsIncomingPanel>();
//Pass the PublicUserData into this function
incomingPanel.Create(userResult.Value);
}
});
}
}
});
AccelBytePlugin.GetLobby().ListOutgoingFriends(result =>
{
if (result.IsError)
{
Debug.LogWarning($"Unable to get Outgoing Requests Code: {result.Error.Code}, Message: {result.Error.Message}");
}
else
{
if (result.Value.friendsId.Length <= 0)
{
pendingOutgoingRequestPlaceholder.gameObject.SetActive(true);
}
else
{
pendingOutgoingRequestPlaceholder.gameObject.SetActive(false);
}
foreach (string userID in result.Value.friendsId)
{
AccelBytePlugin.GetUser().GetUserByUserId(userID, userResult =>
{
if (userResult.IsError)
{
Debug.LogWarning($"Unable to User Code: {userResult.Error.Code}, Message: {userResult.Error.Message}");
}
else
{
FriendsOutgoingPanel outgoingPanel = Instantiate(pendingOutgoingRequestsPrefab, pendingOutgoingRequestsContent).GetComponent<FriendsOutgoingPanel>();
outgoingPanel.Create(userResult.Value);
}
});
}
}
});
}
private void DisplayBlocked()
{
//Cleanup First
LoopThroughTransformAndDestroy(blockedContent.transform,blockedDisplayPlaceholder);
//Get Blocked List
AccelBytePlugin.GetLobby().GetListOfBlockedUser(result =>
{
//Check for an Error
if (result.IsError)
{
Debug.LogWarning($"Unable to get Blocked Player List Code: {result.Error.Code}, Message: {result.Error.Message}");
blockedDisplayPlaceholder.gameObject.SetActive(true);
}
else
{
blockedDisplayPlaceholder.gameObject.SetActive(false);
//Loop through all the UserID's returned by the callback and get their PublicUserData
foreach (BlockedData blockedUser in result.Value.data)
{
//Request the PublicUserData for the specific User
AccelBytePlugin.GetUser().GetUserByUserId(blockedUser.blockedUserId, userResult =>
{
//If it's an Error, report it and do nothing else
if (userResult.IsError)
{
Debug.LogWarning($"Unable to User Code: {userResult.Error.Code}, Message: {userResult.Error.Message}");
}
//If we have valid data, Instantiate the Prefab for the specific UI Piece and call relevant functions
else
{
FriendsBlockedPanel blockedPanel = Instantiate(blockedUserPrefab, blockedContent).GetComponent<FriendsBlockedPanel>();
//Pass the PublicUserData into this function
blockedPanel.Create(userResult.Value);
}
});
}
}
});
}
/// <summary>
/// A utility function to Destroy all Children of the parent transform. Optionally do not remove a specific Transform
/// </summary>
/// <param name="parent">Parent Object to destroy children</param>
/// <param name="doNotRemove">Optional specified Transform that should NOT be destroyed</param>
private static void LoopThroughTransformAndDestroy(Transform parent, Transform doNotRemove = null)
{
//Loop through all the children and add them to a List to then be deleted
List<GameObject> toBeDeleted = new List<GameObject>();
foreach (Transform t in parent)
{
//except the Do Not Remove transform if there is one
if (t != doNotRemove)
{
toBeDeleted.Add(t.gameObject);
}
}
//Loop through list and Delete all Children
for (int i = 0; i < toBeDeleted.Count; i++)
{
Destroy(toBeDeleted[i]);
}
}
}
// Copyright (c) 2021 - 2022 AccelByte Inc. All Rights Reserved.
// This is licensed software from AccelByte Inc, for limitations
// and restrictions contact your company contract manager.
using System.Collections;
using System.Collections.Generic;
using AccelByte.Api;
using AccelByte.Models;
using UnityEngine;
using UnityEngine.UI;
using Image = UnityEngine.UI.Image;
public class FriendStatusPanel : MonoBehaviour
{
[SerializeField]
private Image profilePicture;
[SerializeField]
private Image statusDisplay;
[SerializeField]
private Button chatButton;
[SerializeField]
private Button inviteToPartyButton;
[SerializeField]
private Button unfriendButton;
[SerializeField]
private Button blockButton;
[SerializeField]
private Text displayNameText;
[SerializeField]
private Text onlineStatusText;
PublicUserData _userData;
void SetOnlineStatus(FriendsStatusNotif notification)
{
switch (notification.availability)
{
case "offline":
onlineStatusText.text = "Offline";
statusDisplay.color = Color.black;
break;
case "online":
onlineStatusText.text = "Online";
statusDisplay.color = Color.green;
break;
case "busy":
onlineStatusText.text = "Busy";
statusDisplay.color = Color.yellow;
break;
case "invisible":
onlineStatusText.text = "Offline";
statusDisplay.color = Color.black;
break;
default:
onlineStatusText.text = $"INVALID UNHANDLED {notification.availability}";
statusDisplay.color = Color.magenta;
break;
}
Debug.Log($"Friend Status for {notification.userID} changed to {notification.availability}");
}
public void Create(PublicUserData pud)
{
_userData = pud;
displayNameText.text = _userData.displayName;
}
public void UpdateUser(FriendsStatusNotif notification)
{
SetOnlineStatus(notification);
}
/// <summary>
/// Setup UI Button Listener
/// </summary>
public void SetupButton()
{
inviteToPartyButton.onClick.AddListener(() =>
{
LobbyHandler.Instance.GetComponent<PartyHandler>().InviteToParty(_userData.userId);
});
unfriendButton.onClick.AddListener(() =>
{
AccelBytePlugin.GetLobby().Unfriend(_userData.userId, result =>
{
if (result.IsError)
{
Debug.Log($"Failed to unfriend a friend: code: {result.Error.Code}, message: {result.Error.Message}");
}
else
{
Debug.Log("Successfully unfriend a friend!");
LobbyHandler.Instance.GetComponent<FriendsManagementHandler>().RefreshFriendsList();
}
});
});
}
}
← Friends Matchmaking →