Skip to main content
Version: v3

Friend Mode

Before continuing, make sure you have finished initializing the SDK.

Responding to Friend Status Changes

With the Friends module, the client can listen to the status changes of the player’s friends and display them to the player in real-time. You’ll need to register an instance for listening to friend status changes before calling the interface for getting the player online. By doing this, the player will be able to receive notifications after they get online:

TDSFriends.FriendStatusChangedDelegate = new TDSFriendStatusChangedDelegate {
// New friend added (triggered together with “Sent friend request accepted”)
OnFriendAdd = friendInfo => {},
// New friend request received
OnNewRequestComing = req => {},
// Sent friend request accepted
OnRequestAccepted = req => {},
// Sent friend request declined
OnRequestDeclined = req => {},
// Friend got online
OnFriendOnline = userId => {},
// Friend got offline
OnFriendOffline = userId => {},
// Friend’s rich presence information changed
OnRichPresenceChanged = (userId, richPresence) => {},
// The current player got online (connection established)
OnConnected = () => {},
// Connection lost; the SDK will try to reconnect automatically
OnDisconnected = () => {},
// Connection error
OnConnectionError = (code, message) => {},
};

The “friends” appearing in the events above refer to the friends under the Friend mode. The SDK doesn’t support listening to the events under the Follow mode.

To stop listening:

TDSFriends.FriendStatusChangedDelegate = null;

Getting the Player Online

After the player logs in, you need to call this interface to establish a persistent connection between the client and the cloud. Once the persistent connection is established, if there is an interruption to the internet connection, the SDK will automatically reconnect once the connection is restored.

await TDSFriends.Online();

Getting the Player Offline

After the player logs out, you need to call this interface to disconnect the client from the cloud.

await TDSFriends.Offline();

Searching for Friends by Nickname

A player can search for friends by nickname without knowing their objectIds. For example, to search for friends with Tarara as their nickname:

ReadOnlyCollection<TDSFriendInfo> friendInfos = await TDSFriends.SearchUserByName("Tarara");
foreach (TDSFriendInfo info in friendInfos) {
// Player data
TDSUser user = info.User;
// Rich presence data; continue reading for more information
Dictionary<string, string> richPresence = RichPresence;
// Whether the friend is online
bool online = info.Online;
}

Notice that in order to use this function, the nickname field has to be set on the built-in account system. See TDS Authentication Guide for more information.

Friend Code

Each logged-in player has a friend code that can be shared with other players so these players can quickly add the current player as their friend.

You can get the friend code of a TDSUser from its shortId field:

// currentUser is a logged in TDSUser
string shortId = currentUser["shortId"];

To search for a player with their friend code:

TDSFriendInfo friendInfo = await TDSFriends.SearchUserByShortCode(shortId);

Searching for Friends With objectId

Besides using nicknames and friend codes, a player can also search for friends with their objectIds.

For example, to search for the friend with 5b0b97cf06f4fd0abc0abe35 as their objectId:

TDSFriendInfo friendInfo = await TDSFriends.SearchUserById("5b0b97cf06f4fd0abc0abe35");

Rich Presence

Rich presence can be used to display the player’s status information like their online status, current hero, and current game mode.

After adding configurations for rich presence on the Developer Center, you can set the content of a player’s rich presence according to the configured fields for rich presence:

await TDSFriends.SetRichPresence("score", "60");

Here score is a rich presence field configured on the Developer Center. There are two types available for each rich presence field:

  • variable: The value is a string. In the code example above, with score configured to be a variable on the Developer Center, the client sets the value of this field to be 60 when updating the rich presence data. The cloud will accordingly return "score": "60" to the client as the rich presence data. You need to handle the localization-related logic yourself so that the player can eventually see something like “Score: 60”.

  • token: The value is a string starting with #. In the example below, the type of display is token, and the client sets the value of this field to be #matching when updating the rich presence data. The cloud will handle the conversion of this value to a localized string and return the result like "display": "Matching" to the client. Notice that if the cloud fails to convert the value, an empty string like "display": " " will be returned.

To set multiple fields at once:

Dictionary<string, string> info = new Dictionary<string, string>();
info.Add("score", "60");
info.Add("display", "#matching");
await TDSFriends.SetRichPresences(info);

You can configure at most 20 rich presence fields on the Developer Center. The key of each field should be no longer than 128 bytes and the value of each field should be no longer than 256 bytes.

You can use the following interface to clear a rich presence field for the current player:

TDSFriends.ClearRichPresence("score");

You can also clear multiple rich presence fields at once:

IEnumerable<string> keys = new string[] {"score", "display"}
await TDSFriends.ClearRichPresences(keys);

The interfaces for setting and clearing rich presence data can each be called at most once every 30 seconds.

There are some REST API interfaces related to rich presence. You can write your own scripts to perform administrative operations on the server side by interacting with these interfaces.

Adding Friends

A player can add friends by entering their friend codes.

await TDSFriends.AddFriendByShortCode(shortId);

If the current player is already on the friend list of the other player, they will immediately become friends. Otherwise, a friend request will be sent to the other player.

Additional properties can be specified when adding friends. For example, to put the other player into the coworkers group:

Dictionary<string, object> attrs = new Dictionary<string, object> {
{ "group", "coworkers" }
};
await TDSFriends.AddFriendByShortCode(shortId, attrs);

A player can also add a TDSUser as their friend with its objectId. For example, assuming Tarara’s objectId is 5b0b97cf06f4fd0abc0abe35, the current player can add Tarara as their friend with the following code:

await TDSFriends.AddFriend("5b0b97cf06f4fd0abc0abe35");

Additional properties can be specified as well when adding friends with objectId:

Dictionary<string, object> attrs = new Dictionary<string, object> {
{ "group", "coworkers" }
};
await TDSFriends.AddFriend("5b0b97cf06f4fd0abc0abe35", attrs);

Deleting Friends

A player can delete their existing friends. For example, after becoming friends with Tarara, the current player changes their mind and doesn’t want to be friends with Tarara anymore:

await TDSFriends.DeleteFriend("5b0b97cf06f4fd0abc0abe35");

Blocklist

Blocking Users

A player can block a user no matter if they’re friends or not. Once a player blocks a user, the ongoing friend requests between them will be deleted, and they won’t be able to send friend requests to each other anymore. Blocked users won’t appear in search results when the player searches for friends. A player can have at most 100 users in their blocklist.

Assuming Tarara’s objectId is 5b0b97cf06f4fd0abc0abe35, to block Tarara:

await TDSFriends.BlockFriend("5b0b97cf06f4fd0abc0abe35");

Unblocking Users

A player can remove a user from their blocklist at any time. If the user used to be a friend of the current player, the user will be added back to the friend list of the current player.

await TDSFriends.UnblockFriend("5b0b97cf06f4fd0abc0abe35");

Retrieving the Blocklist

Use the code below to retrieve the current player’s blocklist with pagination.

var from = 0;
var limit = 100;
ReadOnlyCollection<TDSFriendInfo> friendInfos = await TDSFriends.QueryBlockList(from, limit);
foreach (TDSFriendInfo info in friendInfos) {
// Player data
TDSUser user = info.User;
// Rich presence data
Dictionary<string, string> richPresence = info.RichPresence;
// Whether the friend is online
bool online = info.Online;
}

In the code above:

  • from is the query’s offset. It will be 0 for the first page. For the next page, it will be the number of items retrieved from the last query.
  • limit is the number of items in each page.

Retrieving Friend Requests

There are three possible statuses for each friend request:

  • pending: The target user hasn’t responded yet. This is the default status once a friend request has been created.
  • accepted: The target user accepted the request and they are already friends with the current player.
  • declined: The target user declined the request.

The SDK offers an interface for retrieving friend requests. For example, to retrieve the first 20 requests with their status being pending:

var from = 0;
var limit = 100;
ReadOnlyCollection<LCFriendshipRequest> requests = await TDSFriends.QueryFriendRequestList (
LCFriendshipRequest.STATUS_PENDING, from, limit
);

LCFriendshipRequest.STATUS_PENDING means the status of the friend request is pending. Similarly, LCFriendshipRequest.STATUS_ACCEPTED means accepted and LCFriendshipRequest.STATUS_DECLINED means declined. LCFriendshipRequest.STATUS_ANY means any status.

Use the following interface to include the rich presence data of the initiator of each request in the result:

ReadOnlyCollection<TDSFriendshipRequest> requests = await TDSFriends.QueryFriendRequestWithFriendStateList (
LCFriendshipRequest.STATUS_PENDING, from, limit
);
foreach (TDSFriendshipRequest request in requests) {
// Friend request (see QueryFriendRequestList)
LCFriendshipRequest req = request.FriendshipRequest;
// The rich presence data of the initiator
TDSFriendInfo info = request.FriendInfo;
}

Handling Friend Requests

For each new friend request, the player can accept or decline it. They can also ignore the request or even delete it.

// LCFriendshipRequest request

// Accept
await TDSFriends.AcceptFriendshipRequest(request);
// Accept and add additional attributes
Dictionary<string, object> attrs = new Dictionary<string, object> {
{ "group", "coworkers" }
};
await TDSFriends.AcceptFriendshipRequest(request, attrs);

// Decline
await TDSFriends.DeclineFriendshipRequest(request);
// Delete
await request.Delete();

Note:

  1. If a user declines a friend request from the current player, the player will get an error when they try to send another request to the same user.
  2. If a user deletes a friend request from the current user, the player will be able to send another request to the same user.

Retrieving Friend List

A player can retrieve their own friend list. When performing this operation, a limit and offset can be provided:

var from = 0;
var limit = 100;
ReadOnlyCollection<TDSFriendInfo> friendInfos = await TDSFriends.QueryFriendList(from, limit);
foreach (TDSFriendInfo info in friendInfos) {
// Player data
TDSUser user = info.User;
// Rich presence data
Dictionary<string, string> richPresence = info.RichPresence;
// Whether the friend is online
bool online = info.Online;
}

Check if a User Is a Friend

You can check if a TDSUser is a friend of the current player with its objectId. For example, assuming Tarara’s objectId is 5b0b97cf06f4fd0abc0abe35:

bool isFriend = await TDSFriends.CheckFriendship("5b0b97cf06f4fd0abc0abe35");

Landing Page

A landing page has to be deployed before you use link sharing. The landing page can be deployed on Cloud Engine or any other server that can host a static page. If you plan to use Cloud Engine, keep in mind that the free instances provided by Cloud Engine come with auto-hibernation. Please consider purchasing standard instances.

We provide an [open-source demo landing page] for you to use. You can build, deploy, and use it with your own configurations. Notice that the format of the GAME_ANDROID_LINK environment variable of the demo is scheme://host/path. The values of host and path should be consistent with those written in the AndroidManifest.xml of your Android project.

For example, if the AndroidManifest.xml of your project contains the following configurations:

<activity
android:name="com.tapsdk.friends.TDSFriendsRouterPageActivity"
android:allowTaskReparenting="true"
android:configChanges="keyboardHidden|orientation"
android:exported="true"
android:launchMode="singleTask"
android:screenOrientation="nosensor"
android:theme="@android:style/Theme.Translucent.NoTitleBar">
<intent-filter>
<action android:name="android.intent.action.VIEW" />

<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<data
android:host="APP_ID"
android:path="/friends"
android:scheme="tapsdk" />
<!-- The scheme cannot contain capital letters or underscores <a href="[scheme]://[host]/[path]?[query]">Launch the App</a> -->
</intent-filter>
</activity>

The value of GAME_ANDROID_LINK in your landing page should be tapsdk://APP_ID/friends.

The address of the landing page should be configured in the client:

TDSFriends.SetShareLink("https://please-replace-with-your-domain.example.com");

If the landing page is hosted on Cloud Engine, the address will be https://YOUR_CLOUD_ENGINE_CUSTOM_DOMAIN.

After the landing page has been deployed and the address has been configured in the client, you can call the following interface to generate invitation links:

string inviteUrl = await TDSFriends.GenerateFriendInvitationLink();

The default username in the link will be the nickname of the player. Therefore, you might want to make sure that you have set the nicknames of the users in the built-in account system. See TDS Authentication Guide for more information. To use other names, specify them when calling the above interface. You can also provide other parameters that can be attached to the URL of the invitation link as query parameters. For example, if the player named Tarara wants to use “Taro” as their name and attach a ref=taptap parameter, you can do this:

Dictionary<string, object> parameters = new Dictionary<string, object> {
{ "ref", "taptap" }
};
string inviteUrl = await TDSFriends.GenerateFriendInvitationLink("Taro", parameters);

After the player opens the game with an invitation link, you need to call the following interface. The SDK will automatically send a friend request to the corresponding player.

public class DeepLinkManager : MonoBehaviour
{
// Other logic
private async void onDeepLinkActivated(string url) {
await TDSFriends.HandleFriendInvitationLink(url);
}
}

You can also parse the link with the following interface provided by the SDK and get the player’s objectId and name as well as other parameters. You can perform your custom logic with them.

public class DeepLinkManager : MonoBehaviour
{
// Other logic
private async void onDeepLinkActivated(string url) {
TDSFriendLinkInfo invitation = TDSFriends.ParseFriendInvitationLink(url);
string userObjectId = invitation.Identity;
string name = invitation.RoleName;
Dictionary<string, string> parameters = invitation.Queries;
await TDSFriends.Follow(userObjectId);
}
}