Skip to main content

ChatModels

Data model and interface definitions used in the chat system.

IChatListener Interface

Listener interface for receiving chat events.

MethodDescription
OnConnectedCalled when server connection succeeds
OnDisconnectedCalled when server disconnects
OnErrorCalled when error occurs
OnChannelsCalled when channel list is received
OnSubscribedCalled when subscribing to channel
OnUnSubscribedCalled when unsubscribing from channel
OnPublicMessageCalled when public message is received
OnPrivateMessageCalled when private message is received
OnNotifyMessageCalled when notification message is received
OnPlayerOnlineCalled when player online status is received

Data Models

FChatServerResponse

FieldTypeDescription
ErrorCodeFStringError code
MessageFStringMessage
ServersTArray<FChatServerItem>Server list

FChatServerItem

FieldTypeDescription
AddrFStringServer address
Portint32Server port
SecureFStringSSL usage (Y/N)

FChatMessageModel

FieldTypeDescription
midFStringMessage ID
typeuint8Event type
errorint32Error code
gameIdFStringGame ID
serviceKeyFStringService key
channelIdFStringChannel ID
userUniqueIdFStringUser unique ID
userNameFStringUser name
privateToUserUniqueIdFStringPrivate message target ID
messageFStringMessage content
channelsTArray<FChatChannelInfo>Channel info array
playersTArray<FChatPlayerInfo>Player info array
onlinePlayersTArray<FString>Online player ID array
prevMessageCountint32Number of previous messages to fetch
ipAddrFStringIP address
createdAtFStringCreation time

FChatUserInfo

FieldTypeDescription
visitorIdFStringVisitor ID
visitorNameFStringVisitor name

FChatChannelInfo

FieldTypeDescription
channelFStringChannel name
countint32User count

FChatPlayerInfo

FieldTypeDescription
userUniqueIdFStringUser unique ID
onlineFStringOnline status

Unreal C++ Implementation

Header File (ChatModels.h)

// ChatModels.h
#pragma once

#include "CoreMinimal.h"
#include "Json.h"
#include "JsonUtilities.h"
#include "ChatModels.generated.h"

// Chat event listener interface
class IChatListener
{
public:
virtual ~IChatListener() = default;
virtual void OnConnected() = 0;
virtual void OnDisconnected() = 0;
virtual void OnError(const FString& Code, const FString& Message) = 0;
virtual void OnChannels(const TArray<struct FChatChannelInfo>& Channels) = 0;
virtual void OnSubscribed(const struct FChatUserInfo& User) = 0;
virtual void OnUnSubscribed(const struct FChatUserInfo& User) = 0;
virtual void OnPublicMessage(const struct FChatUserInfo& Sender, const FString& Message) = 0;
virtual void OnPrivateMessage(const struct FChatUserInfo& Sender, const FString& Message) = 0;
virtual void OnNotifyMessage(const struct FChatUserInfo& Sender, const FString& Message) = 0;
virtual void OnPlayerOnline(const TArray<struct FChatPlayerInfo>& Players) = 0;
};

// Server response struct
USTRUCT(BlueprintType)
struct FChatServerItem
{
GENERATED_BODY()

UPROPERTY()
FString Addr;

UPROPERTY()
int32 Port;

UPROPERTY()
FString Secure;

void FromJson(const TSharedPtr<FJsonObject>& JsonObject)
{
JsonObject->TryGetStringField(TEXT("Addr"), Addr);
JsonObject->TryGetNumberField(TEXT("Port"), Port);
JsonObject->TryGetStringField(TEXT("Secure"), Secure);
}
};

USTRUCT(BlueprintType)
struct FChatServerResponse
{
GENERATED_BODY()

UPROPERTY()
FString ErrorCode;

UPROPERTY()
FString Message;

UPROPERTY()
TArray<FChatServerItem> Servers;

bool FromJson(const FString& JsonString)
{
TSharedPtr<FJsonObject> JsonObject;
TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(JsonString);

if (FJsonSerializer::Deserialize(Reader, JsonObject) && JsonObject.IsValid())
{
JsonObject->TryGetStringField(TEXT("ErrorCode"), ErrorCode);
JsonObject->TryGetStringField(TEXT("Message"), Message);

const TArray<TSharedPtr<FJsonValue>>* ServersArray;
if (JsonObject->TryGetArrayField(TEXT("Servers"), ServersArray))
{
for (const auto& ServerValue : *ServersArray)
{
FChatServerItem Item;
Item.FromJson(ServerValue->AsObject());
Servers.Add(Item);
}
}
return true;
}
return false;
}
};

// Chat user info
USTRUCT(BlueprintType)
struct FChatUserInfo
{
GENERATED_BODY()

UPROPERTY()
FString visitorId;

UPROPERTY()
FString visitorName;
};

// Channel info
USTRUCT(BlueprintType)
struct FChatChannelInfo
{
GENERATED_BODY()

UPROPERTY()
FString channel;

UPROPERTY()
int32 count;

void FromJson(const TSharedPtr<FJsonObject>& JsonObject)
{
JsonObject->TryGetStringField(TEXT("channel"), channel);
JsonObject->TryGetNumberField(TEXT("count"), count);
}
};

// Player online info
USTRUCT(BlueprintType)
struct FChatPlayerInfo
{
GENERATED_BODY()

UPROPERTY()
FString userUniqueId;

UPROPERTY()
FString online;

void FromJson(const TSharedPtr<FJsonObject>& JsonObject)
{
JsonObject->TryGetStringField(TEXT("userUniqueId"), userUniqueId);
JsonObject->TryGetStringField(TEXT("online"), online);
}
};

// Chat message model
USTRUCT(BlueprintType)
struct FChatMessageModel
{
GENERATED_BODY()

UPROPERTY()
FString mid;

UPROPERTY()
uint8 type;

UPROPERTY()
int32 error;

UPROPERTY()
FString gameId;

UPROPERTY()
FString serviceKey;

UPROPERTY()
FString channelId;

UPROPERTY()
FString userUniqueId;

UPROPERTY()
FString userName;

UPROPERTY()
FString privateToUserUniqueId;

UPROPERTY()
FString message;

UPROPERTY()
TArray<FChatChannelInfo> channels;

UPROPERTY()
TArray<FChatPlayerInfo> players;

UPROPERTY()
TArray<FString> onlinePlayers;

UPROPERTY()
int32 prevMessageCount;

UPROPERTY()
FString ipAddr;

UPROPERTY()
FString createdAt;

FString ToJson() const
{
TSharedPtr<FJsonObject> JsonObject = MakeShareable(new FJsonObject);

JsonObject->SetStringField(TEXT("mid"), mid);
JsonObject->SetNumberField(TEXT("type"), type);
JsonObject->SetStringField(TEXT("gameId"), gameId);
JsonObject->SetStringField(TEXT("serviceKey"), serviceKey);
JsonObject->SetStringField(TEXT("channelId"), channelId);
JsonObject->SetStringField(TEXT("userUniqueId"), userUniqueId);
JsonObject->SetStringField(TEXT("userName"), userName);
if (!privateToUserUniqueId.IsEmpty())
JsonObject->SetStringField(TEXT("privateToUserUniqueId"), privateToUserUniqueId);
if (!message.IsEmpty())
JsonObject->SetStringField(TEXT("message"), message);
JsonObject->SetNumberField(TEXT("prevMessageCount"), prevMessageCount);
JsonObject->SetStringField(TEXT("ipAddr"), ipAddr);
JsonObject->SetStringField(TEXT("createdAt"), createdAt);

if (onlinePlayers.Num() > 0)
{
TArray<TSharedPtr<FJsonValue>> PlayersArray;
for (const FString& PlayerId : onlinePlayers)
{
PlayersArray.Add(MakeShareable(new FJsonValueString(PlayerId)));
}
JsonObject->SetArrayField(TEXT("onlinePlayers"), PlayersArray);
}

FString OutputString;
TSharedRef<TJsonWriter<>> Writer = TJsonWriterFactory<>::Create(&OutputString);
FJsonSerializer::Serialize(JsonObject.ToSharedRef(), Writer);
return OutputString;
}

bool FromJson(const FString& JsonString)
{
TSharedPtr<FJsonObject> JsonObject;
TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(JsonString);

if (FJsonSerializer::Deserialize(Reader, JsonObject) && JsonObject.IsValid())
{
JsonObject->TryGetStringField(TEXT("mid"), mid);
int32 TypeInt;
if (JsonObject->TryGetNumberField(TEXT("type"), TypeInt))
type = static_cast<uint8>(TypeInt);
JsonObject->TryGetNumberField(TEXT("error"), error);
JsonObject->TryGetStringField(TEXT("gameId"), gameId);
JsonObject->TryGetStringField(TEXT("serviceKey"), serviceKey);
JsonObject->TryGetStringField(TEXT("channelId"), channelId);
JsonObject->TryGetStringField(TEXT("userUniqueId"), userUniqueId);
JsonObject->TryGetStringField(TEXT("userName"), userName);
JsonObject->TryGetStringField(TEXT("privateToUserUniqueId"), privateToUserUniqueId);
JsonObject->TryGetStringField(TEXT("message"), message);
JsonObject->TryGetNumberField(TEXT("prevMessageCount"), prevMessageCount);
JsonObject->TryGetStringField(TEXT("ipAddr"), ipAddr);
JsonObject->TryGetStringField(TEXT("createdAt"), createdAt);

const TArray<TSharedPtr<FJsonValue>>* ChannelsArray;
if (JsonObject->TryGetArrayField(TEXT("channels"), ChannelsArray))
{
for (const auto& ChannelValue : *ChannelsArray)
{
FChatChannelInfo Info;
Info.FromJson(ChannelValue->AsObject());
channels.Add(Info);
}
}

const TArray<TSharedPtr<FJsonValue>>* PlayersArray;
if (JsonObject->TryGetArrayField(TEXT("players"), PlayersArray))
{
for (const auto& PlayerValue : *PlayersArray)
{
FChatPlayerInfo Info;
Info.FromJson(PlayerValue->AsObject());
players.Add(Info);
}
}

return true;
}
return false;
}
};

// Filter words response
USTRUCT(BlueprintType)
struct FChatFilterResponse
{
GENERATED_BODY()

UPROPERTY()
FString ErrorCode;

UPROPERTY()
FString Message;

UPROPERTY()
TArray<FString> FilterWords;

bool FromJson(const FString& JsonString)
{
TSharedPtr<FJsonObject> JsonObject;
TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(JsonString);

if (FJsonSerializer::Deserialize(Reader, JsonObject) && JsonObject.IsValid())
{
JsonObject->TryGetStringField(TEXT("ErrorCode"), ErrorCode);
JsonObject->TryGetStringField(TEXT("Message"), Message);

const TArray<TSharedPtr<FJsonValue>>* WordsArray;
if (JsonObject->TryGetArrayField(TEXT("FilterWords"), WordsArray))
{
for (const auto& WordValue : *WordsArray)
{
FilterWords.Add(WordValue->AsString());
}
}
return true;
}
return false;
}
};