GS2-Chat

text chat function

GS2-Chat allows you to add text chat to your game. Text chat requires an always-on session to detect new messages and has complex server requirements.

Game Server Services frees you from the hassle of managing these always-on sessions.

Room

To start using GS2-Chat, you must first create a room. Rooms can be created freely by the player, or you can have a room created for you by the developer.

One thing to keep in mind is that GS2-Chat only guarantees a maximum of 3 messages per second per room. Posting more than this may cause errors. Therefore, it is not suitable for requirements such as social networking timelines where a large number of players are stored in a single room.

Passwords

Rooms can be assigned a password. The password must be specified when retrieving messages from a password-protected room or when posting a message.

Subscription

Players can subscribe to a room to receive notifications of new messages in the room. Messages can be categorized, and subscriptions can be made for each category in the room.

In a guild chat implementation, only messages from the guild master can be set to a special category, so that guild members can be sure to subscribe only to messages from the guild master.

Notification by subscription is handled by the GS2-Gateway’s notification functionality, but the GS2-Gateway does not have the ability to subscribe to messages when the player being notified is offline. The GS2-Gateway does provide a feature for out-of-game notifications, such as mobile push notifications.

There is no explicit limit on the number of people who can subscribe to a room, but GS2-Gateway API requests are required to send notifications, so the GS2-Gateway API usage fee is charged per notification. Also, the more notifications you have, the longer it will take for the notifications to reach you.

actor Player1
actor Player2
participant "GS2-Chat#Room"
participant "GS2-Gateway#Namespace"
participant "Firebase Cloud Messaging"
Player1 -> "GS2-Chat#Room" : Subscribe
Player2 -> "GS2-Chat#Room" : Post Message
"GS2-Chat#Room" -> "GS2-Gateway#Namespace" : Send Notification to Player1
"GS2-Gateway#Namespace" -> "Firebase Cloud Messaging" : Notification(if player is offline)
"GS2-Gateway#Namespace" -> Player1 : Notification
Player1 -> "GS2-Chat#Room" : Load New Message

Messages

You can send messages to a room. Messages will only be kept for the last 24 hours; earlier messages will be deleted.

NG Words

The message payload may contain inappropriate words. By working with GS2-Script, you can refuse to post messages that contain inappropriate words or rewrite the message payload.

Because GS2-Script can output HTTP communications, it can also forward them to its own NG word check server for processing.

actor Player
participant "GS2-Chat#Room"
participant "GS2-Script#Script"
Player -> "GS2-Chat#Room" : Post Message
"GS2-Chat#Room" -> "GS2-Script#Script" : Trigger post message
"GS2-Script#Script" -> "GS2-Chat#Room" : Continue? / Replaced Message

Implementation Example

Creating a room

    var result = await gs2.Chat.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).CreateRoomAsync();
    const auto Domain = Gs2->Chat->Namespace(
    "namespace-0001" // namespaceName
    )->Me(
    AccessToken
    );
    const auto Future = Domain->CreateRoom(
    "room-0001", // name
    nullptr, // metadata
    nullptr, // password
    nullptr // whiteListUserIds
    );
    Future->StartSynchronousTask();
    if (!TestFalse(WHAT, Future->GetTask().IsError())) return false;

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

Room Subscription

    var result = await gs2.Chat.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Subscribe(
        roomName: "room-0001"
    ).SubscribeAsync(
        notificationTypes: new [] {
            new Gs2.Unity.Gs2Chat.Model.EzNotificationType {
                category = 0,
                enableTransferMobilePushNotification = false,
            },
        }
    );
    const auto Domain = Gs2->Chat->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        AccessToken
    )->Subscribe(
        "room-0001" // roomName
    );
    const auto Future = Domain->Subscribe(
        []
        {
            const auto v = MakeShared<TArray<TSharedPtr<Gs2::Chat::Model::FNotificationType>>>();
            v->Add(MakeShared<Gs2::Chat::Model::FNotificationType>());
            return v;
        }() // notificationTypes
    );
    Future->StartSynchronousTask();
    if (!TestFalse(WHAT, Future->GetTask().IsError())) return false;

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

Room Unsubscribe

    var result = await gs2.Chat.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Subscribe(
        roomName: "room-0001"
    ).UnsubscribeAsync(
    );
    const auto Domain = Gs2->Chat->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        AccessToken
    )->Subscribe(
        "room-0001" // roomName
    );
    const auto Future = Domain->Unsubscribe(
    );
    Future->StartSynchronousTask();
    if (!TestFalse(WHAT, Future->GetTask().IsError())) return false;

Posting a message

    var result = await gs2.Chat.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Room(
        roomName: "room-0001",
        password: null
    ).PostAsync(
        metadata: "MESSAGE_0001",
        category: 0
    );
    const auto Domain = Gs2->Chat->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        AccessToken
    )->Subscribe(
        "room-0001" // roomName
    );
    const auto Future = Domain->Subscribe(
        []
        {
            const auto v = MakeShared<TArray<TSharedPtr<Gs2::Chat::Model::FNotificationType>>>();
            v->Add(MakeShared<Gs2::Chat::Model::FNotificationType>());
            return v;
        }() // notificationTypes
    );
    Future->StartSynchronousTask();
    if (!TestFalse(WHAT, Future->GetTask().IsError())) return false;

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

Get a list of messages

    var items = await gs2.Chat.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Room(
        roomName: "room-0001",
        password: null
    ).MessagesAsync(
    ).ToListAsync();
    const auto Domain = Gs2->Chat->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        AccessToken
    )->Room(
        "room-0001", // roomName
        nullptr // password
    );
    const auto It = Domain->Messages(
    );
    for (auto Item : *It)
    {

    }

Message receipt notification handling

MessagesAsync responds to the cache if one exists, and the cache of data available in the message list is automatically updated by the SDK when it receives a message receipt notification. Therefore, there is usually no need to handle this event, and by calling MessagesAsync when necessary, the cache can usually be used to access the most recent message list.

    gs2.Chat.OnPostNotification += PostNotification =>
    {
        var namespaceName = PostNotification.NamespaceName;
        var roomName = PostNotification.RoomName;
    };
    Gs2->Chat->PostNotificationEvent.AddLambda([](const auto Notification)
    {

    });

Detailed reference