Friends & Presence: a real feature, not a roadmap item
Groups: bcchat implements both together, and registers presence per-group here rather than per-friend; Global Chat for the RTT dispatch pattern this reuses.
brainCloud's Friend service works alongside the RTT Presence extension to let a player see who else in their network is online, live. Two reference apps exercise it, scoped two different ways: the bcchat React example (repositories/js-examples/bcchat) fetches a friend list, then scopes presence per group; the BombersRTT Unity example (repositories/unity-examples/BombersRTT) scopes presence directly to the friend list itself, no group involved. An earlier draft of this series described this feature as a roadmap item, SDK surface that "exists today but isn't yet exercised by any reference app." That was incorrect. This article corrects that framing with what's actually there.
How it works
- Fetch friends once, right after connecting to RTT. listFriends(platform, includeSummaryData) returns the roster in a single call. No separate "check who's online" call is needed to render the list.
- The two reference apps pick two different presence scopes, and both are real. bcchat registers per group the player belongs to (registerListenersForGroup); BombersRTT registers across the whole friend list directly (registerListenersForFriends + getPresenceOfFriends). Presence also supports an arbitrary-profile-list scope (registerListenersForProfiles) for cases outside both. Which one to use follows from what the UI needs to show.
- Live presence changes arrive through the same RTT callback as chat. They're tagged service: "presence", operation: "INCOMING".
- Adding or removing a friend is fire-and-forget here. This reference app skips any request/accept handshake. The UI updates optimistically, and addFriends/removeFriends confirms the change server-side.
Code
this.bcWrapper.rttService.registerRTTChatCallback(this.onRttMessage.bind(this));
this.bcWrapper.rttService.registerRTTPresenceCallback(this.onRttMessage.bind(this));fetchFriendList()
{
this.bcWrapper.friend.listFriends(this.bcWrapper.friend.friendPlatform.All, false, result =>
{
if (result.status === 200)
{
let state = this.state;
state.chatData.friends = result.data.friends;
// ...
}
});
}this.bcWrapper.presence.registerListenersForGroup(group.groupId, true, result =>
{
if (result.status === 200)
{
result.data.presence.forEach(presence =>
{
var member = group.members.find(member => presence.user.id === member.id);
if (member)
{
member.pic = presence.user.pic || member.pic;
member.online = presence.online;
}
});
}
});onRttMessage(message)
{
if (message.service === "chat" && message.operation === "INCOMING") { /* ... */ }
else if (message.service === "presence" && message.operation === "INCOMING")
{
var from = message.data.from;
let state = this.state;
state.chatData.groups.forEach(group =>
{
group.members?.forEach(member =>
{
if (member.id === from.id) member.online = message.data.online;
});
});
this.setState(state);
}
}this.bcWrapper.friend.addFriends([friend.id], result => { /* ... */ });
this.bcWrapper.friend.removeFriends([friend.id], result => { /* ... */ });private void OnEnableRTTSuccess()
{
GCore.Wrapper.RTTService.RegisterRTTPresenceCallback(OnPresenceCallback);
GCore.Wrapper.Client.PresenceService.RegisterListenersForFriends(platform, true, presenceSuccess);
OnUpdateStats();
}
private void presenceSuccess(string in_data, object obj)
{
GFriendsManager.Instance.GetPresenceOfFriends(OnGetPresenceOfFriendsSuccess);
GCore.Wrapper.Client.PresenceService.SetVisibility(true);
GPlayerMgr.Instance.UpdateActivity(GPlayerMgr.LOCATION_MAIN_MENU, GPlayerMgr.STATUS_IDLE, "", "", true);
}
// GFriendsManager.cs
public void GetPresenceOfFriends(SuccessCallback in_success = null, FailureCallback in_failure = null)
{
GCore.Wrapper.Client.PresenceService.GetPresenceOfFriends(m_platform, m_includeOffline, OnGetPresenceOfFriendsSuccess + in_success, OnGetPresenceOfFriendsFailed + in_failure);
}Gotchas worth knowing up front
- RegisterListenersForFriends is real and live, just not in bcchat. bcchat only registers per group; BombersRTT is the reference app that scopes presence to the whole friend list instead (RegisterListenersForFriends + GetPresenceOfFriends, plus SetVisibility(true) so the player shows up as online to their friends at all).
- Chat and presence pushes arrive on the same kind of RTT callback, distinguished only by service. A handler checking operation alone, without also checking service, will misread one for the other.
- addFriends here is unilateral. There's no pending-invite state in this reference app: anyone can add anyone. Mutual consent, where needed, has to be built as a separate layer; the call itself doesn't enforce it.