Instant Chat
1. Overview
This document introduces the use of the in-game Instant Chat feature.
Instant Chat: This is used for instant text chatting among multiple people. All players who join a given channel can chat with each other. When all the players in a chat leave the channel or go offline, the channel is automatically deleted. Instant Chat application scenarios: Instant Chat can be used among players on the same team in a battle or for a custom player-initiated multi-person chat function.
In addition to the Instant Chat, some PGOS services have built-in text chat functions. For details, see the Party and Lobby docs.
After completing this tutorial, developers will know:
- The basic concepts of the PGOS instant chat.
- How to join/leave an instant chat.
- How to send and receive instant chat messages.
- Instant chat events introduction and how to monitor them.
2. General Sequence
Here is a general sequence for using the instant chat:
3. Definition
- Chat channel: The channel of an instant chat. Channel IDs are used to distinguish different channels. Players who join the same channel can chat with each other.
4. Using Instant Chat
4.1 Join an Instant Chat
Before calling other instant chat functions, the player must join a channel first, otherwise these functions will not work. Players can join a channel by calling the JoinInstantChat
interface.
/**
* Join a text channel chat
*
* @param ChatChannelId A custom unique ID used to identify the channel (in game scope), must be 127 characters or less, can use battle-session-id which base on UUID with 36 characters.
*/
void JoinInstantChat(
const FString& ChatChannelId,
TFunction<void(const FPgosResult& Ret, const FClientJoinInstantChatResult* Data)> Callback) const;
Developers can generate an instant chat channel ID based on the service module instance ID that uses instant chat.
Typical application scenario: Using instant chat in a battle.
battle_session_id
is a 36-character UUID. You can use battle_session_id
to splice other information as ChatChannelId
. If a player in the battle needs to join multiple instant chat channels, you can set multiple ChatChannelId
values by adding different information to the end of the battle_session_id
.
struct FClientBattleSessionInfo
{
/** The battle session id to query */
FString battle_session_id;
...
};
Call JoinInstantChat
from InstantChat module as follows:
#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"
void SomeClass::JoinInstantChat(const FString& ChatChannelId)
{
auto instant_chat = IPgosSDKCpp::Get().GetClientInstantChatAPI();
if (instant_chat)
{
instant_chat->JoinInstantChat(ChatChannelId, [](const FPgosResult& Ret, const FClientJoinInstantChatResult* Result)
{
if (Ret.err_code == 0)
{
UE_LOG(LogTemp, Log, TEXT("JoinInstantChat Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("JoinInstantChat Failed: err_code=(%d), err_msg=%s]"), Ret.err_code, *Ret.msg);
}
});
}
}
Note: A single player can join up to 20 channels at the same time.
4.2 Leave an Instant Chat
If the player doesn't want to chat anymore in one instant chat channel, then the player can leave the current channel by calling the LeaveInstantChat
interface.
When players go offline, PGOS will automatically remove them from the instant chat channels they joined.
/**
* Leave a text channel chat
*
* @param ChatChannelId The chat channel id to leave
*/
void LeaveInstantChat(
const FString& ChatChannelId,
TFunction<void(const FPgosResult& Ret)> Callback) const;
Call LeaveInstantChat
from InstantChat module as follows:
#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"
void SomeClass::LeaveInstantChat(const FString& ChatChannelId)
{
auto instant_chat = IPgosSDKCpp::Get().GetClientInstantChatAPI();
if (instant_chat)
{
instant_chat->LeaveInstantChat(ChatChannelId, [](const FPgosResult& Ret)
{
if (Ret.err_code == 0)
{
UE_LOG(LogTemp, Log, TEXT("LeaveInstantChat Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("LeaveInstantChat Failed: err_code=(%d), err_msg=%s]"), Ret.err_code, *Ret.msg);
}
});
}
}
4.3 Send instant chat message
After joining an instant chat channel, players can send messages to the channel, which the other players on the channel will receive.
/**
* Send instant text chat message
*
* @param Params Request struct for sending instant chat message
*/
void SendInstantChatTextMsg(
const FClientSendInstantChatMsgParams& Params,
TFunction<void(const FPgosResult& Ret, const FClientChatMsgInfo* Data)> Callback) const;
/**
* Send instant custom chat message
*
* @param Params Request struct for sending instant chat message
*/
void SendInstantChatCustomMsg(
const FClientSendInstantChatMsgParams& Params,
TFunction<void(const FPgosResult& Ret, const FClientChatMsgInfo* Data)> Callback) const;
Call SendInstantChatTextMsg
/SendInstantChatCustomMsg
from InstantChat module as follows:
#include "PgosSDKCpp.h"
void SomeUObjectClass::SendInstantChatTextMsg()
{
auto InstantChat = IPgosSDKCpp::Get().GetClientInstantChatAPI();
if (InstantChat)
{
FClientSendInstantChatMsgParams Params;
InstantChat->SendInstantChatTextMsg(Params, [](const FPgosResult& Ret, const FClientChatMsgInfo* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("SendInstantChatTextMsg Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("SendInstantChatTextMsg Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
void SomeUObjectClass::SendInstantChatCustomMsg()
{
auto InstantChat = IPgosSDKCpp::Get().GetClientInstantChatAPI();
if (InstantChat)
{
FClientSendInstantChatMsgParams Params;
InstantChat->SendInstantChatCustomMsg(Params, [](const FPgosResult& Ret, const FClientChatMsgInfo* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("SendInstantChatCustomMsg Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("SendInstantChatCustomMsg Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
4.4 Get all members in a channel
After joining a channel, players can view all members of the channel and the number of members.
/**
* Get all members in a channel
*
* @param ChatChannelId The chat channel id
*/
void GetInstantChatMembers(
const FString& ChatChannelId,
TFunction<void(const FPgosResult& Ret, const FClientGetInstantChatMembersResult* Data)> Callback) const;
/**
* Get all member IDs in a channel.
*
* @param ChatChannelId The chat channel id.
*/
void GetInstantChatMemberIDs(
const FString& ChatChannelId,
TFunction<void(const FPgosResult& Ret, const FClientGetInstantChatMemberIDsResult* Data)> Callback) const;
/**
* Get the num of members in a channel.
*
* @param ChatChannelId The chat channel id.
*/
void GetInstantChatMemberCount(
const FString& ChatChannelId,
TFunction<void(const FPgosResult& Ret, const FClientGetInstantChatMemberCountResult* Data)> Callback) const;
Call GetInstantChatMembers
/GetInstantChatMemberIDs
/GetInstantChatMemberCount
from InstantChat module as follows:
#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"
void SomeClass::GetInstantChatMembers(const FString& ChatChannelId)
{
auto instant_chat = IPgosSDKCpp::Get().GetClientInstantChatAPI();
if (instant_chat)
{
instant_chat->GetInstantChatMembers(ChatChannelId, [](const FPgosResult& Ret, const FClientGetInstantChatMembersResult* Data)
{
if (Ret.err_code == 0)
{
UE_LOG(LogTemp, Log, TEXT("GetInstantChatMembers Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("GetInstantChatMembers Failed: err_code=(%d), err_msg=%s]"), Ret.err_code, *Ret.msg);
}
});
}
}
void SomeUObjectClass::GetInstantChatMemberIDs()
{
auto InstantChat = IPgosSDKCpp::Get().GetClientInstantChatAPI();
if (InstantChat)
{
FString ChatChannelId;
InstantChat->GetInstantChatMemberIDs(ChatChannelId, [](const FPgosResult& Ret, const FClientGetInstantChatMemberIDsResult* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("GetInstantChatMemberIDs Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("GetInstantChatMemberIDs Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
void SomeUObjectClass::GetInstantChatMemberCount()
{
auto InstantChat = IPgosSDKCpp::Get().GetClientInstantChatAPI();
if (InstantChat)
{
FString ChatChannelId;
InstantChat->GetInstantChatMemberCount(ChatChannelId, [](const FPgosResult& Ret, const FClientGetInstantChatMemberCountResult* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("GetInstantChatMemberCount Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("GetInstantChatMemberCount Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
4.5 Monitor Instant Chat Events
Some events will be triggered when using the instant chat:
- OnInstantChatMemberJoined: Triggered when someone joins the instant chat channel. The event results are saved in
FClientInstantChatMemberJoinedEvt
. - OnInstantChatMemberLeft: Triggered when someone leaves the instant chat channel. The event results are saved in
FClientInstantChatMemberLeftEvt
. - OnReceiveInstantChatMsg: Triggered when an instant chat message is received. The event results are saved in
FClientReceiveInstantChatMsgEvt
.
struct FClientInstantChatMemberJoinedEvt
{
/** Instant chat channel the player joined */
FString chat_channel_id;
/** Players added to the instant chat */
TArray<FPlayerInfo> added_members;
};
struct FClientInstantChatMemberLeftEvt
{
/** Instant chat channel the player left */
FString chat_channel_id;
/** Players left from the channel */
TArray<FPlayerInfo> left_members;
};
struct FClientChatMsgInfo
{
/** The player who sent the message */
FPlayerInfo sender;
/** The time the message was sent */
int64 sent_time;
/** The type of the message */
EClientChatMsgType msg_type;
/** The message to be sent */
FClientChatMsgContent content;
/** The sequence number of the message */
int64 seq;
/** Additional information added by the game */
FString custom_data;
}
struct FClientReceiveInstantChatMsgEvt
{
/** ID of chat channel where the message was received */
FString chat_channel_id;
/** Instant chat message received */
FClientChatMsgInfo chat_msg_info;
};
Monitor instant chat events from InstantChat module as follows:
#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"
void SomeClass::MonitorInstantChatEvents()
{
auto instant_chat = IPgosSDKCpp::Get().GetClientInstantChatAPI();
if (instant_chat)
{
instant_chat->OnInstantChatMemberJoined().AddUObject(this, &SomeClass::OnInstantChatMemberJoined);
instant_chat->OnInstantChatMemberLeft().AddUObject(this, &SomeClass::OnInstantChatMemberLeft);
instant_chat->OnReceiveInstantChatMsg().AddUObject(this, &SomeClass::OnReceiveInstantChatMsg);
}
}
void SomeClass::OnInstantChatMemberJoined(const FClientInstantChatMemberJoinedEvt& Event)
{
UE_LOG(LogTemp, Log, TEXT("OnInstantChatMemberJoined"));
}
void SomeClass::OnInstantChatMemberLeft(const FClientInstantChatMemberLeftEvt& Event)
{
UE_LOG(LogTemp, Log, TEXT("OnInstantChatMemberLeft"));
}
void SomeClass::OnReceiveInstantChatMsg(const FClientReceiveInstantChatMsgEvt& Event)
{
UE_LOG(LogTemp, Log, TEXT("OnReceiveInstantChatMsg"));
}
5. Key Error Handling
Error Code | Relevant API | Handling Suggestion |
---|---|---|
kCltSdkChatChannelIdIsInvalid | JoinInstantChat | channel_id is invalid, must not exceed 127 characters and cannot be empty. The game can prompt the player a message like "Input must not exceed 127 characters and cannot be empty." |
kBackendMemberIsInChatChannel | JoinInstantChat | The player is already in chat channel. The game can prompt the player a message like "You should leave the current instant channel and then try again" |
kBackendMemberIsNotInChatChannel | LeaveInstantChat SendInstantChatTextMsg SendInstantChatCustomMsg GetInstantChatMembers | The player is already not in chat channel. The game can prompt the player a message like "You should join an instant channel first." |
kBackendChatChannelNotExist | LeaveInstantChat SendInstantChatTextMsg SendInstantChatCustomMsg GetInstantChatMembers | The chat channel is not exit. The game can prompt the player a message like "You should join an instant channel first." |
kBackendProfaneWords | SendInstantChatTextMsg SendInstantChatCustomMsg | The msg contains profane words. The game can prompt the player a message like "Please remove profane words to send message" |