GS2-Friend
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;
}