GS2-Chat

Text chat feature

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 (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();

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 (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();

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 (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 (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 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(
    );
    TArray<Gs2::UE5::Chat::Model::FEzMessagePtr> Result;
    for (auto Item : *It)
    {
        if (Item.IsError())
        {
            return false;
        }
        Result.Add(Item.Current());
    }

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)
    {

    });

Script Triggers

Event triggers can be configured in the namespace to invoke custom scripts before and after room operations. Scripts support both synchronous and asynchronous execution, with asynchronous processing enabling integration with GS2-Script or Amazon EventBridge for external services.

Main event triggers and script setting names are:

  • createRoomScript (completion notification: createRoomDone): before and after room creation
  • deleteRoomScript (completion notification: deleteRoomDone): before and after room deletion
  • postMessageScript (completion notification: postMessageDone): before and after message posting
  • subscribeRoomScript (completion notification: subscribeRoomDone): before and after room subscription
  • unsubscribeRoomScript (completion notification: unsubscribeRoomDone): before and after unsubscribing

Push Notifications

Main push notifications and setting names are:

  • postNotification: When a message is posted
  • createRoomNotification: When a room is created
  • deleteRoomNotification: When a room is deleted

Other Features

Categories that Cannot be Posted from Clients

By setting rejectAccessTokenPost to true in the CategoryModel master data, the corresponding category becomes inaccessible for posting using access tokens. This feature can be used to create categories that can only be posted through scripts, useful for storing system messages.

Player Room Creation Permission

The allowCreateRoom setting in the namespace controls whether players can freely create rooms.

allowCreateRoom=true: Players can create their own rooms allowCreateRoom=false: Only rooms prepared by administrators are available

Use this setting when you want to prevent excessive room creation or limit available rooms to specific ones.

Detailed Reference