GS2-Friend

Friend/Follow function

Provides the ability to create a game-specific social graph. While social graphs are a feature that platforms also offer, there is also value in creating your own in-game social graph.

Platform friend relationships tend to be reluctant to sign up. This is because there is a case of “I want to play the game I’m playing with this person, but I don’t want to play other games with them”. If we treat the social graph provided by the platform as reflecting a relationship closer to real life, and the game-specific social graph as reflecting a relationship within that game, players will feel more comfortable using the friend feature.

Friends

In order to become friends, a mutual, consensual relationship is required.

A friend relationship is established when one of the players who wishes to become a friend sends a friend request to the other player, and the player who receives the friend request accepts it.

Follow

A follow can be established without the consent of the other party.

The person being followed has no way of knowing who is following them as a list. This specification may seem strange when you imagine the specifications of a social network follow. However, we have looked at the specifications of many games that implement the follow feature in-game and found that it is not necessary.

If a player who follows you goes on an adventure with your ghost character, you can I am not really interested in who went on the adventure with me, as it is enough for me to share the rewards I received from the adventure.

You cannot get a list, but when you send a reward message to the GS2’s inbox, you can include the user IDs of the players who did the quest with you so that you can share with whom you received the quest’s rewards.

Profile

GS2-Friend provides an area to hold a player’s profile. The profile can have any value and there are three areas.

  • “Public Profile”, which can be freely viewed by other players.
  • “Follower Profile”, which can be viewed by players who follow the player.
  • “Friend Profile”, which can be viewed by friends.

Each of these can be used for different purposes.

Blacklist

After playing a game for a long time, there may be players who make you feel uncomfortable. This feature allows you to create a list of such players and make it permanent.

It is only a persistent feature, and simply adding them here does not perform any function. It is necessary to pass the list to GS2-Matchmaking’s matchmaking conditions, or use the list recorded here separately as needed.

Example implementation

Updating Profile

    var result = await gs2.Friend.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Profile(
    ).UpdateProfileAsync(
        publicProfile: "public",
        followerProfile: "follower",
        friendProfile: "friend"
    );
    var item = await result.ModelAsync();
    const auto Domain = Gs2->Friend->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        AccessToken
    )->Profile(
    );
    const auto Future = Domain->UpdateProfile(
        "public", // publicProfile
        "follower", // followerProfile
        "friend" // friendProfile
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError()) return false;

    // obtain changed values / result values
    const auto Future2 = Future->GetTask().Result()->Model();
    Future2->StartSynchronousTask();
    if (Future2->GetTask().IsError()) return false;
    const auto Result = Future2->GetTask().Result();

Get own profile

    var item = await gs2.Friend.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Profile(
    ).ModelAsync();
    const auto Domain = Gs2->Friend->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        AccessToken
    )->Profile(
    );
    const auto item = Domain.Model();

Get someone else’s public profile

    var item = await gs2.Friend.Namespace(
        namespaceName: "namespace-0001"
    ).User(
        userId: "user-0001"
    ).PublicProfile(
    ).ModelAsync();
    const auto Domain = Gs2->Friend->Namespace(
        "namespace-0001" // namespaceName
    )->User(
        "user-0001" // userId
    )->PublicProfile(
    );
    const auto item = Domain.Model();

Send a friend request

    var result = await gs2.Friend.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).SendRequestAsync(
        targetUserId: "user-0002"
    );
    const auto Future = Gs2->Friend->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        AccessToken
    )->SendRequest(
        "user-0002"
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError()) return false;

Get a list of friend requests you have sent

    var items = await gs2.Friend.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).SendRequestsAsync(
    ).ToListAsync();
    const auto It = Gs2->Friend->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        AccessToken
    )->SendRequests(
    );
    TArray<Gs2::UE5::Friend::Model::FEzFriendRequestPtr> Result;
    for (auto Item : *It)
    {
        if (Item.IsError())
        {
            return false;
        }
        Result.Add(Item.Current());
    }

Get a list of received friend requests

    var items = await gs2.Friend.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).ReceiveRequestsAsync(
    ).ToListAsync();
    const auto It = Gs2->Friend->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        AccessToken
    )->SendRequests(
    );
    TArray<Gs2::UE5::Friend::Model::FEzFriendRequestPtr> Result;
    for (auto Item : *It)
    {
        if (Item.IsError())
        {
            return false;
        }
        Result.Add(Item.Current());
    }

Allow friend requests

    var result = await gs2.Friend.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).ReceiveFriendRequest(
        fromUserId: "user-0002"
    ).AcceptAsync(
    );
    const auto Future = Gs2->Friend->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        AccessToken
    )->ReceiveFriendRequest(
        nullptr, // targetUserId
        "user-0002" // fromUserId
    )->Accept(
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError()) return false;

Deny friend request

    var result = await gs2.Friend.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).ReceiveFriendRequest(
        fromUserId: "user-0002"
    ).RejectAsync(
    );
    const auto Future = Gs2->Friend->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        AccessToken
    )->ReceiveFriendRequest(
        nullptr, // targetUserId
        "user-0002" // fromUserId
    )->Reject(
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError()) return false;

Get a list of friends

    var items = await gs2.Friend.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).FriendsAsync(
    ).ToListAsync();
    const auto It = Gs2->Friend->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        AccessToken
    )->Friends(
    );
    TArray<Gs2::UE5::Friend::Model::FEzFriendUserPtr> Result;
    for (auto Item : *It)
    {
        if (Item.IsError())
        {
            return false;
        }
        Result.Add(Item.Current());
    }

Delete a friend

    var result = await gs2.Friend.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Friend(
    ).FriendUser(
        targetUserId: "user-0002"
    ).DeleteFriendAsync(
    );
    const auto Future = Gs2->Friend->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        AccessToken
    )->Friend(
    )->FriendUser(
        "user-0002" // targetUserId
    )->DeleteFriend(
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError()) return false;

Follow a player

    var result = await gs2.Friend.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).FollowUser(
        targetUserId: "user-0002",
        withProfile: true
    ).FollowAsync(
    );
    const auto Future = Gs2->Friend->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        AccessToken
    )->FollowUser(
        "user-0002", // targetUserId
        true // withProfile
    )->Follow(
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError()) return false;

Get a list of followers

    var items = await gs2.Friend.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).FollowsAsync(
    ).ToListAsync();
    const auto It = Gs2->Friend->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        AccessToken
    )->Follows(
    );
    TArray<Gs2::UE5::Friend::Model::FEzFollowUserPtr> Result;
    for (auto Item : *It)
    {
        if (Item.IsError())
        {
            return false;
        }
        Result.Add(Item.Current());
    }

Unfollow a player

    var result = await gs2.Friend.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).FollowUser(
        targetUserId: "user-0002",
        withProfile: false
    ).UnfollowAsync(
    );
    const auto Domain = Gs2->Friend->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        AccessToken
    )->FollowUser(
        "user-0002", // targetUserId
        false // withProfile
    );
    const auto Future = Domain->Unfollow(
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

Detailed Reference