diff --git a/chat-call.mdx b/chat-call.mdx index b85b12834..ccc6b5559 100644 --- a/chat-call.mdx +++ b/chat-call.mdx @@ -213,6 +213,7 @@ npx @cometchat/skills add } href="/sdk/android/overview" horizontal /> } href="/sdk/flutter/overview" horizontal /> } href="/sdk/ionic/overview" horizontal /> + } href="/sdk/unreal/overview" horizontal /> diff --git a/docs.json b/docs.json index a064bb587..a014a3746 100644 --- a/docs.json +++ b/docs.json @@ -4613,6 +4613,45 @@ } ] }, + { + "dropdown": "Unreal Engine", + "icon": "/images/icons/unreal.svg", + "pages": [ + "sdk/unreal/overview", + "sdk/unreal/setup", + "sdk/unreal/key-concepts", + { + "group": "Authentication", + "pages": [ + "sdk/unreal/authentication" + ] + }, + { + "group": "Messaging", + "pages": [ + "sdk/unreal/send-message", + "sdk/unreal/receive-messages", + "sdk/unreal/real-time-events", + "sdk/unreal/typing-indicators", + "sdk/unreal/delivery-read-receipts", + "sdk/unreal/connection-status" + ] + }, + { + "group": "Users & Groups", + "pages": [ + "sdk/unreal/users", + "sdk/unreal/groups" + ] + }, + { + "group": "Reference", + "pages": [ + "sdk/unreal/reference" + ] + } + ] + }, { "dropdown": "Ionic (Legacy)", "icon": "/images/icons/ionic.svg", diff --git a/images/icons/unreal.svg b/images/icons/unreal.svg new file mode 100644 index 000000000..0cdc617af --- /dev/null +++ b/images/icons/unreal.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/images/unreal_chat_sample.png b/images/unreal_chat_sample.png new file mode 100644 index 000000000..90003ba71 Binary files /dev/null and b/images/unreal_chat_sample.png differ diff --git a/sdk/unreal/authentication.mdx b/sdk/unreal/authentication.mdx new file mode 100644 index 000000000..00d208c81 --- /dev/null +++ b/sdk/unreal/authentication.mdx @@ -0,0 +1,267 @@ +--- +title: "Authentication" +description: "Log users in and out of CometChat in your Unreal Engine project." +--- + +## Create User + +Before you log in a user, the user must exist in CometChat. + +1. **For proof of concept / MVPs**: Create users via the [CometChat Dashboard](https://app.cometchat.com). +2. **For production apps**: Use the [Create User REST API](https://api-explorer.cometchat.com/reference/creates-user) when your user signs up. + + +**Sample Users** + +CometChat provides 5 pre-created users for testing: `cometchat-uid-1`, `cometchat-uid-2`, `cometchat-uid-3`, `cometchat-uid-4`, and `cometchat-uid-5`. + + +--- + +## Login using Auth Key + + +This authentication method is ideal for **proof-of-concept** development or early-stage apps. For production environments, we recommend using an **Auth Token** instead of an Auth Key for enhanced security. + + +### Auth Flow + +```mermaid +flowchart LR + A["Configure"] --> B["Bind Delegates"] --> C["Login Async"] + C -->|"Success"| D["User Authenticated"] + C -->|"Failure"| E["Handle Error"] + D --> F["SDK Ready — Send messages, fetch data"] + + style A fill:#333,stroke:#666,color:#fff + style B fill:#333,stroke:#666,color:#fff + style C fill:#444,stroke:#888,color:#fff + style D fill:#333,stroke:#666,color:#fff + style E fill:#555,stroke:#999,color:#ccc + style F fill:#333,stroke:#666,color:#fff +``` + +The Login node authenticates a user with CometChat. You should call it: + +1. When the user is logging in for the first time +2. When `IsLoggedIn` returns `false` + + + +1. Get a reference to the **CometChat Subsystem** +2. Call the **Login Async** node +3. Wire the **On Success** and **On Failure** pins + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| Uid | `FString` | The unique ID of the user to log in | +| Auth Key | `FString` | Your CometChat Auth Key | + + +```cpp +#include "CometChatSubsystem.h" +#include "AsyncActions/CometChatLoginAction.h" + +void AMyActor::BeginPlay() +{ + Super::BeginPlay(); + + // 1. Configure the SDK (do this once) + UCometChatSubsystem* Chat = GetGameInstance()->GetSubsystem(); + Chat->Configure(TEXT("YOUR_APP_ID"), TEXT("us")); + + // 2. Bind real-time events before login + Chat->OnMessageReceived.AddDynamic(this, &AMyActor::OnMessage); + + // 3. Login + if (!Chat->IsLoggedIn()) + { + auto* Login = UCometChatLoginAction::LoginAsync( + this, + TEXT("cometchat-uid-1"), + TEXT("YOUR_AUTH_KEY") + ); + Login->OnSuccess.AddDynamic(this, &AMyActor::OnLoginSuccess); + Login->OnFailure.AddDynamic(this, &AMyActor::OnLoginFailed); + Login->Activate(); + } +} + +void AMyActor::OnLoginSuccess() +{ + UE_LOG(LogTemp, Log, TEXT("Login successful!")); +} + +void AMyActor::OnLoginFailed(const FString& Error) +{ + UE_LOG(LogTemp, Error, TEXT("Login failed: %s"), *Error); +} +``` + + + + +**UID format**: UIDs can be alphanumeric with underscores and hyphens. Spaces, punctuation, and other special characters are not allowed. + + +--- + +## Login using Auth Token + + +This is the **recommended authentication method for production** apps. Auth Tokens are generated server-side using the CometChat REST API and provide enhanced security since your Auth Key is never exposed on the client. + + +### How Auth Tokens Work + +```mermaid +flowchart LR + A["Your Backend"] --> B["CometChat REST API"] + B -->|"Returns Auth Token"| A + A -->|"Sends Token to Client"| C["Unreal Client"] + C --> D["Login with Auth Token"] + D -->|"Success"| E["User Authenticated"] + D -->|"Failure"| F["Handle Error"] + + style A fill:#333,stroke:#666,color:#fff + style B fill:#333,stroke:#666,color:#fff + style C fill:#444,stroke:#888,color:#fff + style D fill:#444,stroke:#888,color:#fff + style E fill:#333,stroke:#666,color:#fff + style F fill:#555,stroke:#999,color:#ccc +``` + +1. Your backend calls the [Create Auth Token REST API](https://api-explorer.cometchat.com/reference/create-authtoken) with the user's UID +2. The API returns an Auth Token +3. Your backend sends the token to the Unreal client +4. The client calls `LoginWithAuthTokenAsync` with the token + + + +1. Get a reference to the **CometChat Subsystem** +2. Call the **Login With Auth Token Async** node +3. Wire the **On Success** and **On Failure** pins + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| Auth Token | `FString` | The auth token received from your backend | + + +```cpp +#include "CometChatSubsystem.h" +#include "AsyncActions/CometChatLoginWithAuthTokenAction.h" + +void AMyActor::LoginWithToken(const FString& AuthToken) +{ + UCometChatSubsystem* Chat = GetGameInstance()->GetSubsystem(); + + if (!Chat->IsLoggedIn()) + { + auto* Login = UCometChatLoginWithAuthTokenAction::LoginWithAuthTokenAsync( + this, + AuthToken + ); + Login->OnSuccess.AddDynamic(this, &AMyActor::OnLoginSuccess); + Login->OnFailure.AddDynamic(this, &AMyActor::OnLoginFailed); + Login->Activate(); + } +} + +void AMyActor::OnLoginSuccess() +{ + UE_LOG(LogTemp, Log, TEXT("Auth token login successful!")); +} + +void AMyActor::OnLoginFailed(const FString& Error) +{ + UE_LOG(LogTemp, Error, TEXT("Auth token login failed: %s"), *Error); +} +``` + + + + +**Security**: Never hardcode Auth Tokens in your client. Always fetch them from your backend at runtime. + + +--- + +## Check Login State + +Before performing operations, you can check whether a user is currently logged in. + + + +Call the **Is Logged In** node on the CometChat Subsystem. It returns a `bool`. + + +```cpp +UCometChatSubsystem* Chat = GetGameInstance()->GetSubsystem(); + +if (Chat->IsLoggedIn()) +{ + // User is authenticated — safe to send messages, fetch data, etc. +} +``` + + + +--- + +## Logout + +Logs the current user out and disconnects the real-time WebSocket. + + + +Call the **Logout Async** node on the CometChat Subsystem. Wire the **On Success** and **On Failure** pins. + + +```cpp +#include "AsyncActions/CometChatLogoutAction.h" + +void AMyActor::PerformLogout() +{ + auto* Logout = UCometChatLogoutAction::LogoutAsync(this); + Logout->OnSuccess.AddDynamic(this, &AMyActor::OnLogoutSuccess); + Logout->OnFailure.AddDynamic(this, &AMyActor::OnLogoutFailed); + Logout->Activate(); +} +``` + + + +--- + +## Shutdown + +To fully tear down the SDK (e.g., when your game is closing), call **Shutdown** on the Subsystem. This releases all resources and closes connections. + + + +Call the **Shutdown** node on the CometChat Subsystem. + + +```cpp +UCometChatSubsystem* Chat = GetGameInstance()->GetSubsystem(); +Chat->Shutdown(); +``` + + + + +You typically don't need to call Shutdown manually — the Subsystem's `Deinitialize` handles cleanup when the game instance is destroyed. + + +--- + +## Next Steps + + + + Send your first text message after logging in. + + + Listen for incoming messages and presence updates. + + diff --git a/sdk/unreal/connection-status.mdx b/sdk/unreal/connection-status.mdx new file mode 100644 index 000000000..1c0290cac --- /dev/null +++ b/sdk/unreal/connection-status.mdx @@ -0,0 +1,93 @@ +--- +title: "Connection Status" +description: "Monitor the WebSocket connection state and handle reconnection." +--- + +The CometChat SDK maintains a persistent WebSocket connection for real-time events. The `OnConnectionStateChanged` delegate lets you track the connection lifecycle and show appropriate UI (e.g., a "Reconnecting..." banner). + +--- + +## Listen for Connection Changes + + + +1. Get a reference to the **CometChat Subsystem** +2. Drag off and search for **On Connection State Changed** +3. Use **Bind Event** to connect it to a custom event +4. The custom event receives an `ECometChatConnectionState` enum value + + +```cpp +void AMyActor::BeginPlay() +{ + Super::BeginPlay(); + + UCometChatSubsystem* Chat = GetGameInstance()->GetSubsystem(); + Chat->OnConnectionStateChanged.AddDynamic(this, &AMyActor::HandleConnection); +} + +void AMyActor::HandleConnection(ECometChatConnectionState State) +{ + switch (State) + { + case ECometChatConnectionState::Connected: + UE_LOG(LogTemp, Log, TEXT("Connected — real-time events active")); + HideConnectionBanner(); + break; + + case ECometChatConnectionState::Disconnected: + UE_LOG(LogTemp, Warning, TEXT("Disconnected — no real-time events")); + ShowConnectionBanner(TEXT("Connection lost")); + break; + + case ECometChatConnectionState::Reconnecting: + UE_LOG(LogTemp, Warning, TEXT("Reconnecting...")); + ShowConnectionBanner(TEXT("Reconnecting...")); + break; + } +} +``` + + + +--- + +## ECometChatConnectionState + +| Value | Description | +| ----- | ----------- | +| `Connected` | WebSocket is active. Real-time events (messages, presence, typing, receipts) are flowing. | +| `Disconnected` | WebSocket is closed. No real-time events will be received until reconnection. | +| `Reconnecting` | The SDK detected a disconnect and is automatically attempting to reconnect. | + +--- + +## Reconnection Behavior + +The SDK handles reconnection automatically: + +1. When the WebSocket drops (network change, server timeout, etc.), the state moves to `Reconnecting` +2. The SDK retries with exponential backoff +3. On successful reconnection, the state moves back to `Connected` +4. If reconnection fails permanently, the state moves to `Disconnected` + + +**UI pattern**: Show a subtle banner at the top of your chat screen when the state is `Disconnected` or `Reconnecting`. Hide it when `Connected` fires again. This gives players confidence that the chat system is working. + + + +While disconnected, you can still call async nodes like **Get Messages Async** — those use HTTP requests, not the WebSocket. Only real-time push events are affected by the connection state. + + +--- + +## Next Steps + + + + See all five real-time delegates in one place. + + + Complete reference of all nodes, structs, and enums. + + diff --git a/sdk/unreal/delivery-read-receipts.mdx b/sdk/unreal/delivery-read-receipts.mdx new file mode 100644 index 000000000..c435fcdb4 --- /dev/null +++ b/sdk/unreal/delivery-read-receipts.mdx @@ -0,0 +1,96 @@ +--- +title: "Delivery & Read Receipts" +description: "Track when messages are delivered to and read by recipients." +--- + +Delivery and read receipts let you show checkmark indicators (✓ delivered, ✓✓ read) next to messages in your chat UI. The CometChat Unreal SDK delivers these as real-time events through the `OnReceiptReceived` delegate. + +--- + +## Listen for Receipt Events + +Bind to the `OnReceiptReceived` delegate on the Subsystem. + + + +1. Get a reference to the **CometChat Subsystem** +2. Drag off and search for **On Receipt Received** +3. Use **Bind Event** to connect it to a custom event +4. The custom event receives an `FCometChatReceiptEvent` parameter + + +```cpp +void AMyActor::BeginPlay() +{ + Super::BeginPlay(); + + UCometChatSubsystem* Chat = GetGameInstance()->GetSubsystem(); + Chat->OnReceiptReceived.AddDynamic(this, &AMyActor::HandleReceipt); +} + +void AMyActor::HandleReceipt(const FCometChatReceiptEvent& Event) +{ + if (Event.Status == TEXT("delivered")) + { + // Show single checkmark ✓ + MarkMessageDelivered(Event.MessageId); + } + else if (Event.Status == TEXT("read")) + { + // Show double checkmark ✓✓ + MarkMessageRead(Event.MessageId); + } +} +``` + + + +--- + +## FCometChatReceiptEvent + +| Property | Type | Description | +| -------- | ---- | ----------- | +| `MessageId` | `FString` | The message this receipt applies to | +| `Uid` | `FString` | The user who triggered the receipt (the recipient) | +| `Status` | `FString` | `delivered` — message reached the device; `read` — message was viewed | +| `Timestamp` | `int64` | Unix timestamp when the receipt was generated | + +--- + +## Receipt Flow + +```mermaid +flowchart TD + A["Sender sends message"] --> B["Message arrives on recipient's device"] + B --> C["'delivered' receipt"] + C -.-> D["OnReceiptReceived — Status: delivered"] + B --> E["Recipient views message"] + E --> F["'read' receipt"] + F -.-> G["OnReceiptReceived — Status: read"] + + style A fill:#333,stroke:#666,color:#fff + style B fill:#444,stroke:#888,color:#fff + style C fill:#333,stroke:#666,color:#fff + style D fill:#333,stroke:#666,color:#fff + style E fill:#444,stroke:#888,color:#fff + style F fill:#333,stroke:#666,color:#fff + style G fill:#333,stroke:#666,color:#fff +``` + + +A `read` receipt implies `delivered`. If you receive a `read` event for a message you haven't seen a `delivered` event for, treat it as both delivered and read. + + +--- + +## Next Steps + + + + Monitor the WebSocket connection state. + + + See all five delegates in one place. + + diff --git a/sdk/unreal/groups.mdx b/sdk/unreal/groups.mdx new file mode 100644 index 000000000..75515c162 --- /dev/null +++ b/sdk/unreal/groups.mdx @@ -0,0 +1,194 @@ +--- +title: "Groups" +description: "Create, join, leave, and message groups in your Unreal Engine game." +--- + +Groups let multiple users communicate in a shared conversation. The CometChat Unreal SDK provides async nodes for creating groups, joining existing ones, leaving, and sending/receiving group messages. + +### Group Lifecycle + +```mermaid +flowchart LR + A["Create Group Async"] --> B["Group exists"] + B --> C["Join Group Async"] + C --> D["Member of group"] + D --> E["Send / Receive messages"] + D --> F["Leave Group Async"] + + style A fill:#444,stroke:#888,color:#fff + style B fill:#333,stroke:#666,color:#fff + style C fill:#444,stroke:#888,color:#fff + style D fill:#333,stroke:#666,color:#fff + style E fill:#333,stroke:#666,color:#fff + style F fill:#555,stroke:#999,color:#ccc +``` + +--- + +## Create a Group + +Create a new group with a name and an initial set of member UIDs. + + + +Call the **Create Group Async** node. + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| Name | `FString` | Display name for the group | +| Member Ids | `TArray` | UIDs of users to add as initial members | + +**On Success** returns an `FCometChatGroup` with the server-assigned `Guid`. + + +```cpp +#include "AsyncActions/CometChatCreateGroupAction.h" + +void AMyActor::CreateLobbyGroup() +{ + TArray Members; + Members.Add(TEXT("cometchat-uid-1")); + Members.Add(TEXT("cometchat-uid-2")); + Members.Add(TEXT("cometchat-uid-3")); + + auto* Action = UCometChatCreateGroupAction::CreateGroupAsync( + this, + TEXT("Game Lobby"), // Group name + Members // Initial members + ); + Action->OnSuccess.AddDynamic(this, &AMyActor::OnGroupCreated); + Action->OnFailure.AddDynamic(this, &AMyActor::OnGroupCreateFailed); + Action->Activate(); +} + +void AMyActor::OnGroupCreated(const FCometChatGroup& Group) +{ + UE_LOG(LogTemp, Log, TEXT("Group created: %s (GUID: %s)"), + *Group.Name, *Group.Guid); +} + +void AMyActor::OnGroupCreateFailed(const FString& Error) +{ + UE_LOG(LogTemp, Error, TEXT("Create group failed: %s"), *Error); +} +``` + + + +--- + +## Join a Group + +Join an existing group by its GUID. + + + +Call the **Join Group Async** node. + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| Guid | `FString` | The unique identifier of the group to join | + +**On Success** fires with no output — the user is now a member. + + +```cpp +#include "AsyncActions/CometChatJoinGroupAction.h" + +void AMyActor::JoinGroup(const FString& Guid) +{ + auto* Action = UCometChatJoinGroupAction::JoinGroupAsync(this, Guid); + Action->OnSuccess.AddDynamic(this, &AMyActor::OnGroupJoined); + Action->OnFailure.AddDynamic(this, &AMyActor::OnJoinFailed); + Action->Activate(); +} + +void AMyActor::OnGroupJoined() +{ + UE_LOG(LogTemp, Log, TEXT("Successfully joined the group")); +} + +void AMyActor::OnJoinFailed(const FString& Error) +{ + UE_LOG(LogTemp, Error, TEXT("Join failed: %s"), *Error); +} +``` + + + +--- + +## Leave a Group + +Leave a group you're currently a member of. + + + +Call the **Leave Group Async** node. + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| Guid | `FString` | The unique identifier of the group to leave | + +**On Success** fires with no output. + + +```cpp +#include "AsyncActions/CometChatLeaveGroupAction.h" + +void AMyActor::LeaveGroup(const FString& Guid) +{ + auto* Action = UCometChatLeaveGroupAction::LeaveGroupAsync(this, Guid); + Action->OnSuccess.AddDynamic(this, &AMyActor::OnGroupLeft); + Action->OnFailure.AddDynamic(this, &AMyActor::OnLeaveFailed); + Action->Activate(); +} + +void AMyActor::OnGroupLeft() +{ + UE_LOG(LogTemp, Log, TEXT("Left the group")); +} + +void AMyActor::OnLeaveFailed(const FString& Error) +{ + UE_LOG(LogTemp, Error, TEXT("Leave failed: %s"), *Error); +} +``` + + + +--- + +## Send a Group Message + +Send a text message to all members of a group. See [Send a Message → Group Messages](/sdk/unreal/send-message#send-a-group-message) for details. + +--- + +## Fetch Group Message History + +Retrieve previous messages from a group with pagination. See [Receive Messages → Group Messages](/sdk/unreal/receive-messages#fetch-group-messages) for details. + +--- + +## FCometChatGroup Properties + +| Property | Type | Description | +| -------- | ---- | ----------- | +| `Guid` | `FString` | Server-assigned unique group identifier | +| `Name` | `FString` | Group display name | +| `Description` | `FString` | Group description text | +| `MemberIds` | `TArray` | UIDs of current group members | + +--- + +## Next Steps + + + + Send messages to users and groups. + + + Listen for messages, presence, typing, and more. + + diff --git a/sdk/unreal/key-concepts.mdx b/sdk/unreal/key-concepts.mdx new file mode 100644 index 000000000..a0c03be3d --- /dev/null +++ b/sdk/unreal/key-concepts.mdx @@ -0,0 +1,216 @@ +--- +title: "Key Concepts" +description: "Understand the architecture, patterns, and data types used by the CometChat Unreal SDK." +--- + +Before diving into individual features, it helps to understand the three building blocks of the plugin: the **Subsystem**, **Latent Async Nodes**, and **Real-Time Delegates**. + +--- + +## The Subsystem + +`UCometChatSubsystem` is a [UGameInstanceSubsystem](https://dev.epicgames.com/documentation/en-us/unreal-engine/programming-subsystems-in-unreal-engine) — Unreal creates one instance automatically when your game starts, and it lives for the entire session. You never need to spawn or manage it yourself. + + + +Get a reference from any Blueprint: + +**Get Game Instance** → **Get Subsystem** → select **CometChatSubsystem** + + +```cpp +UCometChatSubsystem* Chat = GetGameInstance()->GetSubsystem(); +``` + + + +The Subsystem handles: +- **Configuration** — storing your App ID and Region +- **SDK lifecycle** — creating and shutting down the underlying C++ SDK +- **Auth state** — tracking whether a user is logged in +- **Real-time events** — exposing multicast delegates for push notifications + +--- + +## Latent Async Nodes + +Every SDK operation that talks to the network (Login, Send Message, Get Messages, etc.) is exposed as a **latent async action** — a Blueprint node with two output execution pins: + +| Pin | When it fires | +| --- | ------------- | +| **On Success** | The operation completed successfully. Output data is available on the success pin. | +| **On Failure** | Something went wrong. An `FString` error message describes what happened. | + +### How an Async Node Executes + +```mermaid +flowchart LR + A["Blueprint calls Async Node"] --> B["C++ SDK makes request"] --> C{"Response"} + C -->|"Success"| D["On Success pin fires"] + C -->|"Error"| E["On Failure pin fires"] + + style A fill:#333,stroke:#666,color:#fff + style B fill:#333,stroke:#666,color:#fff + style C fill:#444,stroke:#888,color:#fff + style D fill:#333,stroke:#666,color:#fff + style E fill:#555,stroke:#999,color:#ccc +``` + +In C++, these are `UCometChatAsyncAction` subclasses. You create them with a static factory method, bind delegates, and call `Activate()`: + +```cpp +auto* Action = UCometChatLoginAction::LoginAsync(this, TEXT("user-123"), TEXT("auth-key")); +Action->OnSuccess.AddDynamic(this, &AMyActor::HandleLoginSuccess); +Action->OnFailure.AddDynamic(this, &AMyActor::HandleLoginFailure); +Action->Activate(); +``` + + +All async callbacks fire on the **Game Thread**, so it's safe to update UI, spawn actors, or call other engine APIs directly from the callback. + + +### Available Async Nodes + +| Category | Node | Success Output | +| -------- | ---- | -------------- | +| Auth | **Login Async** | — | +| Auth | **Logout Async** | — | +| Messaging | **Send Message Async** | `FCometChatMessage` | +| Messaging | **Send Group Message Async** | `FCometChatMessage` | +| Messaging | **Get Messages Async** | `TArray` | +| Messaging | **Get Group Messages Async** | `TArray` + `FCometChatPagination` | +| Users | **Get User Async** | `FCometChatUser` | +| Groups | **Create Group Async** | `FCometChatGroup` | +| Groups | **Join Group Async** | — | +| Groups | **Leave Group Async** | — | + +--- + +## Real-Time Delegates + +The Subsystem exposes five multicast delegates for real-time push events. Bind to them once after calling **Configure**, and they'll fire whenever the server pushes an update. + +| Delegate | Payload Type | Fires When | +| -------- | ------------ | ---------- | +| `OnMessageReceived` | `FCometChatMessage` | A new message arrives in any conversation | +| `OnPresenceChanged` | `FCometChatPresence` | A user goes online, offline, or away | +| `OnTypingChanged` | `FCometChatTypingEvent` | A user starts or stops typing | +| `OnReceiptReceived` | `FCometChatReceiptEvent` | A message is delivered or read | +| `OnConnectionStateChanged` | `ECometChatConnectionState` | WebSocket connects, disconnects, or reconnects | + + + +Drag off the Subsystem reference and search for the delegate name (e.g., **On Message Received**). Use **Bind Event** to wire it to a custom event. + + +```cpp +UCometChatSubsystem* Chat = GetGameInstance()->GetSubsystem(); + +Chat->OnMessageReceived.AddDynamic(this, &AMyActor::HandleNewMessage); +Chat->OnPresenceChanged.AddDynamic(this, &AMyActor::HandlePresence); +Chat->OnTypingChanged.AddDynamic(this, &AMyActor::HandleTyping); +Chat->OnReceiptReceived.AddDynamic(this, &AMyActor::HandleReceipt); +Chat->OnConnectionStateChanged.AddDynamic(this, &AMyActor::HandleConnection); +``` + + + + +Bind your delegates **before** calling Login. Events that arrive between Login and binding will be missed. + + +--- + +## Data Types + +The plugin uses Unreal-native `USTRUCT` types — no `std::string` or STL containers leak into your game code. + +### FCometChatUser + +| Property | Type | Description | +| -------- | ---- | ----------- | +| `Uid` | `FString` | Unique user identifier | +| `Name` | `FString` | Display name | +| `AvatarUrl` | `FString` | URL to the user's avatar image | +| `Status` | `FString` | Current status text | + +### FCometChatMessage + +| Property | Type | Description | +| -------- | ---- | ----------- | +| `Id` | `FString` | Unique message identifier | +| `SenderUid` | `FString` | UID of the sender | +| `ReceiverUid` | `FString` | UID of the receiver (user or group) | +| `Text` | `FString` | Message body | +| `SentAt` | `int64` | Unix timestamp (seconds) when sent | +| `Type` | `FString` | Message type: `text`, `image`, `file`, `custom` | +| `Category` | `FString` | Category: `message`, `action`, `call`, `custom` | +| `ReceiverType` | `FString` | `user` or `group` | +| `ConversationId` | `FString` | Conversation identifier | +| `SenderName` | `FString` | Sender's display name | +| `SenderAvatar` | `FString` | Sender's avatar URL | +| `UpdatedAt` | `int64` | Unix timestamp of last update | + +### FCometChatGroup + +| Property | Type | Description | +| -------- | ---- | ----------- | +| `Guid` | `FString` | Unique group identifier | +| `Name` | `FString` | Group display name | +| `Description` | `FString` | Group description | +| `MemberIds` | `TArray` | UIDs of group members | + +### FCometChatPagination + +| Property | Type | Description | +| -------- | ---- | ----------- | +| `Total` | `int32` | Total messages available | +| `Count` | `int32` | Messages returned in this page | +| `PerPage` | `int32` | Page size requested | +| `CurrentPage` | `int32` | Current page number | +| `TotalPages` | `int32` | Total pages available | +| `HasMore` | `bool` | Whether more pages exist | +| `NextCursor` | `int32` | Message ID to pass as `BeforeMessageId` for the next page | + +### FCometChatPresence + +| Property | Type | Description | +| -------- | ---- | ----------- | +| `Uid` | `FString` | User identifier | +| `Status` | `ECometChatPresenceStatus` | `Online`, `Offline`, or `Away` | +| `LastActiveAt` | `int64` | Unix timestamp of last activity | + +### FCometChatTypingEvent + +| Property | Type | Description | +| -------- | ---- | ----------- | +| `Uid` | `FString` | User who is typing | +| `ConversationId` | `FString` | Conversation where typing is happening | +| `bIsTyping` | `bool` | `true` if started typing, `false` if stopped | + +### FCometChatReceiptEvent + +| Property | Type | Description | +| -------- | ---- | ----------- | +| `MessageId` | `FString` | The message this receipt is for | +| `Uid` | `FString` | User who triggered the receipt | +| `Status` | `FString` | `delivered` or `read` | +| `Timestamp` | `int64` | Unix timestamp of the receipt | + +### Enums + +**ECometChatConnectionState** + +| Value | Description | +| ----- | ----------- | +| `Connected` | WebSocket is connected and active | +| `Disconnected` | WebSocket is disconnected | +| `Reconnecting` | SDK is attempting to reconnect | + +**ECometChatPresenceStatus** + +| Value | Description | +| ----- | ----------- | +| `Online` | User is currently online | +| `Offline` | User is offline | +| `Away` | User is away | diff --git a/sdk/unreal/overview.mdx b/sdk/unreal/overview.mdx new file mode 100644 index 000000000..a3dc2b800 --- /dev/null +++ b/sdk/unreal/overview.mdx @@ -0,0 +1,177 @@ +--- +title: "Overview" +description: "Add in-app chat to your Unreal Engine game using the CometChat SDK plugin." +--- + + + + + + +**Beta Release** — The CometChat Unreal SDK is currently in beta. APIs and features may change, and you may encounter stability issues. + + +This guide walks you through integrating CometChat into an Unreal Engine 5 project. The SDK ships as a native UE5 plugin with full **Blueprint** and **C++** support — so whether you're wiring up a quick prototype in the visual graph or building a production multiplayer title in code, you're covered. + + +Before you begin, we recommend reading the [Key Concepts](/sdk/unreal/key-concepts) page to understand the architecture. + + +--- + +## Supported Platforms + +| Platform | Status | +| -------- | ------ | +| Windows (Win64) | ✅ Supported | +| macOS | ✅ Supported | +| Linux | ✅ Supported | +| iOS | ✅ Supported | +| Android | ✅ Supported | + +--- + +## Minimum Requirements + +- Unreal Engine **5.3** or higher +- C++17 compatible compiler +- [CometChat account](https://app.cometchat.com) with **App ID**, **Region**, and **Auth Key** + +--- + +## Quick Start + +Get up and running in five steps: + + + + [Sign up for CometChat](https://app.cometchat.com), create a new app, and note your **App ID**, **Auth Key**, and **Region**. + + + Copy the `CometChat` plugin into your project's `Plugins/` directory. See [Setup](/sdk/unreal/setup) for details. + + + Call **Configure** on the `CometChatSubsystem` with your App ID and Region. + + + Use the **Login Async** node with a user UID and Auth Key. + + + Use the **Send Message Async** node to send your first message. + + + +--- + +## Architecture + +The plugin has three layers: + +```mermaid +graph TD + A["Your Game — Blueprint / C++"] --> B["Unreal Plugin Layer
Subsystem + Async Nodes + Delegates"] + B --> C["C++ Chat SDK Core"] + C --> D["CometChat Cloud"] + + style A fill:#333,stroke:#666,color:#fff + style B fill:#444,stroke:#888,color:#fff + style C fill:#333,stroke:#666,color:#fff + style D fill:#555,stroke:#999,color:#fff +``` + +- **UCometChatSubsystem** — A `UGameInstanceSubsystem` that owns the SDK lifecycle. Access it from any Actor or Widget. +- **Latent Async Nodes** — Blueprint-friendly async actions with **Success** and **Failure** output pins. +- **Real-Time Delegates** — Multicast delegates on the Subsystem for push events. All fire on the **Game Thread**. + +--- + +## How It Works in Blueprints + +```mermaid +flowchart TD + A["Event BeginPlay"] --> B["Get CometChat Subsystem"] + B --> C["Configure — App Id, Region"] + C --> D["Bind Delegates
OnMessageReceived, OnPresenceChanged"] + D --> E["Login Async"] + E -->|"On Success"| F["Ready"] + E -->|"On Failure"| G["Handle Error"] + + F --> H["Send Message Async"] + F --> I["Get Messages Async"] + F --> J["Create / Join / Leave Group"] + + H -->|"On Success"| K["Update Chat UI"] + I -->|"On Success"| K + + L["CometChat Cloud"] -.->|"WebSocket"| M["OnMessageReceived fires"] + M --> K + + style A fill:#333,stroke:#666,color:#fff + style B fill:#333,stroke:#666,color:#fff + style C fill:#333,stroke:#666,color:#fff + style D fill:#333,stroke:#666,color:#fff + style E fill:#444,stroke:#888,color:#fff + style F fill:#333,stroke:#666,color:#fff + style G fill:#555,stroke:#999,color:#ccc + style H fill:#444,stroke:#888,color:#fff + style I fill:#444,stroke:#888,color:#fff + style J fill:#444,stroke:#888,color:#fff + style K fill:#333,stroke:#666,color:#fff + style L fill:#555,stroke:#999,color:#ccc + style M fill:#333,stroke:#666,color:#fff +``` + +1. **Get the Subsystem** — `Get Game Instance` → `Get Subsystem` → `CometChatSubsystem` +2. **Configure** — Pass your App ID and Region once +3. **Bind Delegates** — Wire up `OnMessageReceived` and other events before Login +4. **Async Nodes** — Every operation has **On Success** and **On Failure** exec pins +5. **Real-Time Events** — Incoming messages and presence updates arrive automatically via delegates + + +All callbacks fire on the **Game Thread** — safe to update UI directly. + + +--- + +## What's Included + +| Category | Capabilities | +| -------- | ------------ | +| **Authentication** | Login, Logout, session check | +| **Messaging** | Send & receive text messages (1:1 and group), message history with pagination | +| **Users** | Fetch user profiles, real-time presence | +| **Groups** | Create, join, leave groups, group messaging | +| **Real-Time Events** | Message received, presence changed, typing indicators, read receipts, connection state | + +--- + +## Sample Users + +CometChat provides 5 pre-created users for testing: + +| UID | Name | +| --- | ---- | +| `cometchat-uid-1` | Andrew Joseph | +| `cometchat-uid-2` | George Alan | +| `cometchat-uid-3` | Nancy Grace | +| `cometchat-uid-4` | Susan Marie | +| `cometchat-uid-5` | Peter Reed | + +--- + +## Next Steps + + + + Install the plugin and configure your project. + + + Understand the Subsystem, async nodes, and event model. + + + Log users in and manage sessions. + + + Send your first text message. + + diff --git a/sdk/unreal/real-time-events.mdx b/sdk/unreal/real-time-events.mdx new file mode 100644 index 000000000..cd7c43fa8 --- /dev/null +++ b/sdk/unreal/real-time-events.mdx @@ -0,0 +1,237 @@ +--- +title: "Real-Time Events" +description: "Listen for incoming messages, presence changes, typing indicators, receipts, and connection state." +--- + +The `UCometChatSubsystem` exposes five multicast delegates that fire whenever the server pushes a real-time update. All delegates are guaranteed to fire on the **Game Thread**, so you can safely update UI directly. + +### Event Flow + +```mermaid +flowchart LR + A["CometChat Cloud"] -.->|"WebSocket"| B["C++ SDK"] + B --> C["Subsystem Delegate"] + C --> D["Your Blueprint / C++ handler"] + + style A fill:#555,stroke:#999,color:#ccc + style B fill:#333,stroke:#666,color:#fff + style C fill:#444,stroke:#888,color:#fff + style D fill:#333,stroke:#666,color:#fff +``` + + +**Bind delegates before calling Login.** Events that arrive between Login completing and your bindings being set up will be missed. + + +--- + +## Binding Delegates + + + +1. Get a reference to the **CometChat Subsystem** +2. Drag off the Subsystem pin and search for the delegate name (e.g., **On Message Received**) +3. Select **Bind Event** to wire it to a custom event node +4. The custom event automatically gets the correct parameter type + + +```cpp +void AMyActor::BeginPlay() +{ + Super::BeginPlay(); + + UCometChatSubsystem* Chat = GetGameInstance()->GetSubsystem(); + + Chat->OnMessageReceived.AddDynamic(this, &AMyActor::HandleMessage); + Chat->OnPresenceChanged.AddDynamic(this, &AMyActor::HandlePresence); + Chat->OnTypingChanged.AddDynamic(this, &AMyActor::HandleTyping); + Chat->OnReceiptReceived.AddDynamic(this, &AMyActor::HandleReceipt); + Chat->OnConnectionStateChanged.AddDynamic(this, &AMyActor::HandleConnection); +} +``` + + + +--- + +## OnMessageReceived + +Fires when a new message arrives in any conversation (1:1 or group). + +| Payload | Type | +| ------- | ---- | +| `Message` | `FCometChatMessage` | + + + +The custom event receives an `FCometChatMessage`. Use `ReceiverType` to check if it's a `user` (1:1) or `group` message, and `ConversationId` to route it to the right chat window. + + +```cpp +void AMyActor::HandleMessage(const FCometChatMessage& Message) +{ + if (Message.ReceiverType == TEXT("group")) + { + UE_LOG(LogTemp, Log, TEXT("[Group %s] %s: %s"), + *Message.ConversationId, *Message.SenderName, *Message.Text); + } + else + { + UE_LOG(LogTemp, Log, TEXT("[DM] %s: %s"), + *Message.SenderName, *Message.Text); + } +} +``` + + + +--- + +## OnPresenceChanged + +Fires when a user's online status changes. + +| Payload | Type | +| ------- | ---- | +| `Presence` | `FCometChatPresence` | + + + +The custom event receives an `FCometChatPresence` with `Uid`, `Status` (an `ECometChatPresenceStatus` enum), and `LastActiveAt`. + + +```cpp +void AMyActor::HandlePresence(const FCometChatPresence& Presence) +{ + FString StatusStr; + switch (Presence.Status) + { + case ECometChatPresenceStatus::Online: StatusStr = TEXT("Online"); break; + case ECometChatPresenceStatus::Offline: StatusStr = TEXT("Offline"); break; + case ECometChatPresenceStatus::Away: StatusStr = TEXT("Away"); break; + } + + UE_LOG(LogTemp, Log, TEXT("%s is now %s"), *Presence.Uid, *StatusStr); +} +``` + + + +For more details, see [Users → User Presence](/sdk/unreal/users#user-presence). + +--- + +## OnTypingChanged + +Fires when a user starts or stops typing in a conversation. + +| Payload | Type | +| ------- | ---- | +| `Event` | `FCometChatTypingEvent` | + + + +The custom event receives an `FCometChatTypingEvent` with `Uid`, `ConversationId`, and `bIsTyping`. + + +```cpp +void AMyActor::HandleTyping(const FCometChatTypingEvent& Event) +{ + if (Event.bIsTyping) + { + UE_LOG(LogTemp, Log, TEXT("%s is typing in %s..."), + *Event.Uid, *Event.ConversationId); + } + else + { + UE_LOG(LogTemp, Log, TEXT("%s stopped typing in %s"), + *Event.Uid, *Event.ConversationId); + } +} +``` + + + +For more details, see [Typing Indicators](/sdk/unreal/typing-indicators). + +--- + +## OnReceiptReceived + +Fires when a message is delivered to or read by the recipient. + +| Payload | Type | +| ------- | ---- | +| `Event` | `FCometChatReceiptEvent` | + + + +The custom event receives an `FCometChatReceiptEvent` with `MessageId`, `Uid`, `Status` (`delivered` or `read`), and `Timestamp`. + + +```cpp +void AMyActor::HandleReceipt(const FCometChatReceiptEvent& Event) +{ + UE_LOG(LogTemp, Log, TEXT("Message %s was %s by %s"), + *Event.MessageId, *Event.Status, *Event.Uid); +} +``` + + + +For more details, see [Delivery & Read Receipts](/sdk/unreal/delivery-read-receipts). + +--- + +## OnConnectionStateChanged + +Fires when the WebSocket connection state changes. + +| Payload | Type | +| ------- | ---- | +| `State` | `ECometChatConnectionState` | + +| Value | Meaning | +| ----- | ------- | +| `Connected` | WebSocket is active and receiving events | +| `Disconnected` | Connection lost | +| `Reconnecting` | SDK is attempting to reconnect automatically | + + + +The custom event receives an `ECometChatConnectionState` enum value. + + +```cpp +void AMyActor::HandleConnection(ECometChatConnectionState State) +{ + switch (State) + { + case ECometChatConnectionState::Connected: + UE_LOG(LogTemp, Log, TEXT("Connected to CometChat")); + break; + case ECometChatConnectionState::Disconnected: + UE_LOG(LogTemp, Warning, TEXT("Disconnected from CometChat")); + break; + case ECometChatConnectionState::Reconnecting: + UE_LOG(LogTemp, Warning, TEXT("Reconnecting...")); + break; + } +} +``` + + + +For more details, see [Connection Status](/sdk/unreal/connection-status). + +--- + +## Delegate Summary + +| Delegate | Payload | Use Case | +| -------- | ------- | -------- | +| `OnMessageReceived` | `FCometChatMessage` | Display new messages in chat UI | +| `OnPresenceChanged` | `FCometChatPresence` | Update online/offline indicators | +| `OnTypingChanged` | `FCometChatTypingEvent` | Show "typing..." animations | +| `OnReceiptReceived` | `FCometChatReceiptEvent` | Show delivery/read checkmarks | +| `OnConnectionStateChanged` | `ECometChatConnectionState` | Show connection status banners | diff --git a/sdk/unreal/receive-messages.mdx b/sdk/unreal/receive-messages.mdx new file mode 100644 index 000000000..699388b8e --- /dev/null +++ b/sdk/unreal/receive-messages.mdx @@ -0,0 +1,220 @@ +--- +title: "Receive Messages" +description: "Fetch message history and listen for incoming messages in real time." +--- + +There are two ways to get messages in the CometChat Unreal SDK: + +1. **Fetch history** — pull previous messages for a conversation using async nodes +2. **Real-time push** — listen for new messages as they arrive via the `OnMessageReceived` delegate + +### How Messages Flow + +```mermaid +flowchart TD + subgraph Fetch["Fetch History"] + A["Get Messages Async"] --> B["CometChat REST API"] --> C["Returns message array"] + end + + subgraph Realtime["Real-Time Push"] + D["CometChat Cloud"] -.->|"WebSocket"| E["OnMessageReceived delegate fires"] + end + + C --> F["Display in Chat UI"] + E --> F + + style A fill:#333,stroke:#666,color:#fff + style B fill:#444,stroke:#888,color:#fff + style C fill:#333,stroke:#666,color:#fff + style D fill:#555,stroke:#999,color:#ccc + style E fill:#333,stroke:#666,color:#fff + style F fill:#444,stroke:#888,color:#fff + style Fetch fill:#2a2a2a,stroke:#555,color:#ccc + style Realtime fill:#2a2a2a,stroke:#555,color:#ccc +``` + +--- + +## Fetch User Messages + +Retrieve the message history for a 1:1 conversation. + + + +Call the **Get Messages Async** node. + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| Uid | `FString` | The UID of the other user in the conversation | +| Limit | `int32` | Maximum number of messages to return (default: 50) | + +**On Success** returns a `TArray` — an array of messages sorted by timestamp. + + +```cpp +#include "AsyncActions/CometChatGetMessagesAction.h" + +void AMyActor::FetchMessages() +{ + auto* Action = UCometChatGetMessagesAction::GetMessagesAsync( + this, + TEXT("cometchat-uid-2"), // Other user's UID + 30 // Limit + ); + Action->OnSuccess.AddDynamic(this, &AMyActor::OnMessagesFetched); + Action->OnFailure.AddDynamic(this, &AMyActor::OnFetchFailed); + Action->Activate(); +} + +void AMyActor::OnMessagesFetched(const TArray& Messages) +{ + for (const FCometChatMessage& Msg : Messages) + { + UE_LOG(LogTemp, Log, TEXT("[%s]: %s"), *Msg.SenderName, *Msg.Text); + } +} + +void AMyActor::OnFetchFailed(const FString& Error) +{ + UE_LOG(LogTemp, Error, TEXT("Fetch failed: %s"), *Error); +} +``` + + + +--- + +## Fetch Group Messages + +Retrieve the message history for a group conversation, with pagination support. + + + +Call the **Get Group Messages Async** node. + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| Guid | `FString` | The group's unique identifier | +| Limit | `int32` | Maximum messages per page (default: 50) | +| Before Message Id | `int32` | Pass `0` for the first page. For subsequent pages, pass the `NextCursor` value from the previous response's `FCometChatPagination`. | + +**On Success** returns two outputs: +- `TArray` — the messages for this page +- `FCometChatPagination` — pagination metadata including `HasMore` and `NextCursor` + + +```cpp +#include "AsyncActions/CometChatGetGroupMessagesAction.h" + +void AMyActor::FetchGroupMessages(int32 BeforeId) +{ + auto* Action = UCometChatGetGroupMessagesAction::GetGroupMessagesAsync( + this, + TEXT("group-abc-123"), // Group GUID + 20, // Limit + BeforeId // 0 for first page + ); + Action->OnSuccess.AddDynamic(this, &AMyActor::OnGroupMessagesFetched); + Action->OnFailure.AddDynamic(this, &AMyActor::OnGroupFetchFailed); + Action->Activate(); +} + +void AMyActor::OnGroupMessagesFetched( + const TArray& Messages, + const FCometChatPagination& Pagination) +{ + for (const FCometChatMessage& Msg : Messages) + { + UE_LOG(LogTemp, Log, TEXT("[%s]: %s"), *Msg.SenderName, *Msg.Text); + } + + if (Pagination.HasMore) + { + // Load next page + FetchGroupMessages(Pagination.NextCursor); + } +} +``` + + + +### Pagination + +The `FCometChatPagination` struct tells you where you are in the message history: + +| Property | Type | Description | +| -------- | ---- | ----------- | +| `Total` | `int32` | Total messages available in the conversation | +| `Count` | `int32` | Messages returned in this page | +| `PerPage` | `int32` | Page size that was requested | +| `HasMore` | `bool` | `true` if there are older messages to fetch | +| `NextCursor` | `int32` | Pass this as `BeforeMessageId` to get the next page | + + +**Infinite scroll pattern**: Start with `BeforeMessageId = 0`, then keep passing `NextCursor` from each response until `HasMore` is `false`. + + +--- + +## Real-Time: Incoming Messages + +To receive messages as they arrive (without polling), bind to the `OnMessageReceived` delegate on the Subsystem. + + + +1. Get a reference to the **CometChat Subsystem** +2. Drag off and search for **On Message Received** +3. Use **Bind Event** to connect it to a custom event +4. The custom event receives an `FCometChatMessage` parameter + +Bind this **before** calling Login so you don't miss any messages. + + +```cpp +void AMyActor::BeginPlay() +{ + Super::BeginPlay(); + + UCometChatSubsystem* Chat = GetGameInstance()->GetSubsystem(); + Chat->OnMessageReceived.AddDynamic(this, &AMyActor::HandleNewMessage); +} + +void AMyActor::HandleNewMessage(const FCometChatMessage& Message) +{ + // This fires on the Game Thread — safe to update UI + UE_LOG(LogTemp, Log, TEXT("New message from %s: %s"), + *Message.SenderName, *Message.Text); + + // Check if it's a group or user message + if (Message.ReceiverType == TEXT("group")) + { + // Group message — Message.ReceiverUid is the group GUID + } + else + { + // 1:1 message — Message.SenderUid is the other user + } +} +``` + + + + +The `OnMessageReceived` delegate fires for **all** conversations — both 1:1 and group. Use `ReceiverType` to distinguish between them, and `ConversationId` to route messages to the right chat window. + + +--- + +## Next Steps + + + + Fetch user profiles and track presence. + + + Create, join, and leave groups. + + + All five real-time delegates explained in detail. + + diff --git a/sdk/unreal/reference.mdx b/sdk/unreal/reference.mdx new file mode 100644 index 000000000..0533b3d7a --- /dev/null +++ b/sdk/unreal/reference.mdx @@ -0,0 +1,189 @@ +--- +title: "API Reference" +description: "Complete reference of all Blueprint nodes, structs, enums, and delegates in the CometChat Unreal SDK." +--- + +This page is a single-stop reference for every public API surface in the CometChat Unreal SDK plugin. + +--- + +## Subsystem Methods + +These are called directly on `UCometChatSubsystem`. + +| Method | Category | Parameters | Returns | Description | +| ------ | -------- | ---------- | ------- | ----------- | +| `Configure` | Config | `AppId: FString`, `Region: FString` | `void` | Initialize the SDK with your CometChat credentials. Must be called before Login. | +| `IsLoggedIn` | Auth | — | `bool` | Returns `true` if a user is currently authenticated. | +| `Shutdown` | Lifecycle | — | `void` | Tear down the SDK and release all resources. | + +--- + +## Async Action Nodes + +Each node is a latent Blueprint action with **On Success** and **On Failure** output pins. In C++, create via the static factory method, bind delegates, and call `Activate()`. + +### Authentication + +| Node | Parameters | Success Output | Description | +| ---- | ---------- | -------------- | ----------- | +| **Login Async** | `Uid: FString`, `AuthKey: FString` | — | Authenticate a user with CometChat. | +| **Logout Async** | — | — | Log out the current user and disconnect. | + +### Messaging + +| Node | Parameters | Success Output | Description | +| ---- | ---------- | -------------- | ----------- | +| **Send Message Async** | `ReceiverUid: FString`, `Text: FString` | `FCometChatMessage` | Send a 1:1 text message. | +| **Send Group Message Async** | `Guid: FString`, `Text: FString` | `FCometChatMessage` | Send a text message to a group. | +| **Get Messages Async** | `Uid: FString`, `Limit: int32` | `TArray` | Fetch message history for a 1:1 conversation. | +| **Get Group Messages Async** | `Guid: FString`, `Limit: int32`, `BeforeMessageId: int32` | `TArray`, `FCometChatPagination` | Fetch paginated message history for a group. | + +### Users + +| Node | Parameters | Success Output | Description | +| ---- | ---------- | -------------- | ----------- | +| **Get User Async** | `Uid: FString` | `FCometChatUser` | Fetch a user's profile. | + +### Groups + +| Node | Parameters | Success Output | Description | +| ---- | ---------- | -------------- | ----------- | +| **Create Group Async** | `Name: FString`, `MemberIds: TArray` | `FCometChatGroup` | Create a new group with initial members. | +| **Join Group Async** | `Guid: FString` | — | Join an existing group. | +| **Leave Group Async** | `Guid: FString` | — | Leave a group. | + +--- + +## Real-Time Delegates + +All delegates are `UPROPERTY(BlueprintAssignable)` on `UCometChatSubsystem`. They fire on the **Game Thread**. + +| Delegate | Payload Type | Fires When | +| -------- | ------------ | ---------- | +| `OnMessageReceived` | `FCometChatMessage` | A new message arrives (1:1 or group) | +| `OnPresenceChanged` | `FCometChatPresence` | A user goes online, offline, or away | +| `OnTypingChanged` | `FCometChatTypingEvent` | A user starts or stops typing | +| `OnReceiptReceived` | `FCometChatReceiptEvent` | A message is delivered or read | +| `OnConnectionStateChanged` | `ECometChatConnectionState` | WebSocket connection state changes | + +--- + +## Structs + +### FCometChatUser + +| Property | Type | Description | +| -------- | ---- | ----------- | +| `Uid` | `FString` | Unique user identifier | +| `Name` | `FString` | Display name | +| `AvatarUrl` | `FString` | URL to avatar image | +| `Status` | `FString` | Current status text | + +### FCometChatMessage + +| Property | Type | Description | +| -------- | ---- | ----------- | +| `Id` | `FString` | Unique message identifier | +| `SenderUid` | `FString` | UID of the sender | +| `ReceiverUid` | `FString` | UID of the receiver (user or group) | +| `Text` | `FString` | Message body | +| `SentAt` | `int64` | Unix timestamp when sent | +| `Type` | `FString` | `text`, `image`, `file`, `custom` | +| `Category` | `FString` | `message`, `action`, `call`, `custom` | +| `ReceiverType` | `FString` | `user` or `group` | +| `ConversationId` | `FString` | Conversation identifier | +| `SenderName` | `FString` | Sender's display name | +| `SenderAvatar` | `FString` | Sender's avatar URL | +| `UpdatedAt` | `int64` | Unix timestamp of last update | + +### FCometChatGroup + +| Property | Type | Description | +| -------- | ---- | ----------- | +| `Guid` | `FString` | Unique group identifier | +| `Name` | `FString` | Group display name | +| `Description` | `FString` | Group description | +| `MemberIds` | `TArray` | UIDs of group members | + +### FCometChatPagination + +| Property | Type | Description | +| -------- | ---- | ----------- | +| `Total` | `int32` | Total messages available | +| `Count` | `int32` | Messages returned in this page | +| `PerPage` | `int32` | Page size requested | +| `CurrentPage` | `int32` | Current page number | +| `TotalPages` | `int32` | Total pages available | +| `HasMore` | `bool` | Whether more pages exist | +| `NextCursor` | `int32` | Message ID for next page (`BeforeMessageId`) | + +### FCometChatPresence + +| Property | Type | Description | +| -------- | ---- | ----------- | +| `Uid` | `FString` | User identifier | +| `Status` | `ECometChatPresenceStatus` | `Online`, `Offline`, or `Away` | +| `LastActiveAt` | `int64` | Unix timestamp of last activity | + +### FCometChatTypingEvent + +| Property | Type | Description | +| -------- | ---- | ----------- | +| `Uid` | `FString` | User who is typing | +| `ConversationId` | `FString` | Conversation where typing occurs | +| `bIsTyping` | `bool` | `true` = started, `false` = stopped | + +### FCometChatReceiptEvent + +| Property | Type | Description | +| -------- | ---- | ----------- | +| `MessageId` | `FString` | The message this receipt is for | +| `Uid` | `FString` | User who triggered the receipt | +| `Status` | `FString` | `delivered` or `read` | +| `Timestamp` | `int64` | Unix timestamp of the receipt | + +--- + +## Enums + +### ECometChatConnectionState + +| Value | Description | +| ----- | ----------- | +| `Connected` | WebSocket is active | +| `Disconnected` | WebSocket is closed | +| `Reconnecting` | SDK is attempting to reconnect | + +### ECometChatPresenceStatus + +| Value | Description | +| ----- | ----------- | +| `Online` | User is currently active | +| `Offline` | User is not connected | +| `Away` | User is connected but idle | + +--- + +## C++ Header Includes + +When working in C++, here are the headers you'll need: + +```cpp +// Subsystem (always needed) +#include "CometChatSubsystem.h" + +// Async action nodes (include as needed) +#include "AsyncActions/CometChatLoginAction.h" +#include "AsyncActions/CometChatLogoutAction.h" +#include "AsyncActions/CometChatSendMessageAction.h" +#include "AsyncActions/CometChatSendGroupMessageAction.h" +#include "AsyncActions/CometChatGetMessagesAction.h" +#include "AsyncActions/CometChatGetGroupMessagesAction.h" +#include "AsyncActions/CometChatGetUserAction.h" +#include "AsyncActions/CometChatCreateGroupAction.h" +#include "AsyncActions/CometChatJoinGroupAction.h" +#include "AsyncActions/CometChatLeaveGroupAction.h" +``` + +All types (`FCometChatUser`, `FCometChatMessage`, `FCometChatGroup`, etc.) are defined in `CometChatSubsystem.h`. diff --git a/sdk/unreal/send-message.mdx b/sdk/unreal/send-message.mdx new file mode 100644 index 000000000..d8b6c36ee --- /dev/null +++ b/sdk/unreal/send-message.mdx @@ -0,0 +1,149 @@ +--- +title: "Send a Message" +description: "Send text messages to users and groups from your Unreal Engine game." +--- + +Once a user is [logged in](/sdk/unreal/authentication), you can send text messages to other users (1:1) or to groups. + +### Message Flow + +```mermaid +flowchart LR + A["Your Game"] --> B["Send Message Async"] + B --> C["C++ SDK"] --> D["CometChat Cloud"] + D --> E["Delivered to recipient"] + B -->|"On Success"| F["FCometChatMessage returned"] + + style A fill:#333,stroke:#666,color:#fff + style B fill:#444,stroke:#888,color:#fff + style C fill:#333,stroke:#666,color:#fff + style D fill:#555,stroke:#999,color:#ccc + style E fill:#333,stroke:#666,color:#fff + style F fill:#333,stroke:#666,color:#fff +``` + +--- + +## Send a User Message + +Send a text message to a specific user by their UID. + + + +1. Get a reference to the **CometChat Subsystem** +2. Call the **Send Message Async** node +3. Wire the **On Success** and **On Failure** pins + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| Receiver Uid | `FString` | The UID of the user to send the message to | +| Text | `FString` | The message body | + +**On Success** returns an `FCometChatMessage` with the sent message details (including the server-assigned `Id` and `SentAt` timestamp). + + +```cpp +#include "AsyncActions/CometChatSendMessageAction.h" + +void AMyActor::SendDirectMessage() +{ + auto* Action = UCometChatSendMessageAction::SendMessageAsync( + this, + TEXT("cometchat-uid-2"), // Receiver UID + TEXT("Hey, want to play?") // Message text + ); + Action->OnSuccess.AddDynamic(this, &AMyActor::OnMessageSent); + Action->OnFailure.AddDynamic(this, &AMyActor::OnMessageFailed); + Action->Activate(); +} + +void AMyActor::OnMessageSent(const FCometChatMessage& Message) +{ + UE_LOG(LogTemp, Log, TEXT("Message sent! ID: %s"), *Message.Id); +} + +void AMyActor::OnMessageFailed(const FString& Error) +{ + UE_LOG(LogTemp, Error, TEXT("Send failed: %s"), *Error); +} +``` + + + +--- + +## Send a Group Message + +Send a text message to a group by its GUID. + + + +Call the **Send Group Message Async** node. + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| Guid | `FString` | The unique identifier of the target group | +| Text | `FString` | The message body | + +**On Success** returns an `FCometChatMessage`. + + +```cpp +#include "AsyncActions/CometChatSendGroupMessageAction.h" + +void AMyActor::SendToGroup() +{ + auto* Action = UCometChatSendGroupMessageAction::SendGroupMessageAsync( + this, + TEXT("group-abc-123"), // Group GUID + TEXT("Team, ready up!") // Message text + ); + Action->OnSuccess.AddDynamic(this, &AMyActor::OnGroupMessageSent); + Action->OnFailure.AddDynamic(this, &AMyActor::OnGroupMessageFailed); + Action->Activate(); +} + +void AMyActor::OnGroupMessageSent(const FCometChatMessage& Message) +{ + UE_LOG(LogTemp, Log, TEXT("Group message sent! ID: %s"), *Message.Id); +} + +void AMyActor::OnGroupMessageFailed(const FString& Error) +{ + UE_LOG(LogTemp, Error, TEXT("Group send failed: %s"), *Error); +} +``` + + + +--- + +## The FCometChatMessage Struct + +Both send operations return an `FCometChatMessage` on success. Here's a quick reference of the key fields: + +| Property | Type | Description | +| -------- | ---- | ----------- | +| `Id` | `FString` | Server-assigned unique message ID | +| `SenderUid` | `FString` | UID of the sender (the logged-in user) | +| `ReceiverUid` | `FString` | UID of the receiver (user UID or group GUID) | +| `Text` | `FString` | The message body | +| `SentAt` | `int64` | Unix timestamp when the message was sent | +| `Type` | `FString` | `text` for text messages | +| `ReceiverType` | `FString` | `user` for 1:1, `group` for group messages | +| `ConversationId` | `FString` | Unique conversation identifier | + +For the full struct definition, see [Key Concepts → FCometChatMessage](/sdk/unreal/key-concepts#fchatmessage). + +--- + +## Next Steps + + + + Fetch message history and listen for incoming messages in real time. + + + Create and manage groups before sending group messages. + + diff --git a/sdk/unreal/setup.mdx b/sdk/unreal/setup.mdx new file mode 100644 index 000000000..12168bc56 --- /dev/null +++ b/sdk/unreal/setup.mdx @@ -0,0 +1,141 @@ +--- +title: "Setup" +description: "Install the CometChat plugin in your Unreal Engine project." +--- + +## Get your Application Keys + +[Sign up for CometChat](https://app.cometchat.com) and then: + +1. Create a new app +2. Head over to the **API & Auth Keys** section and note the **Auth Key**, **App ID**, and **Region** + + +**Minimum Requirements** + +- Unreal Engine **5.3** or higher +- C++17 compatible compiler +- Windows (Win64), macOS, Linux, iOS, or Android target + + +--- + +## Install the Plugin + +### Option 1: Pre-built Plugin (Recommended) + +Copy the `CometChat` plugin folder into your project's `Plugins/` directory: + +``` +YourProject/ +├── Plugins/ +│ └── CometChat/ +│ ├── CometChat.uplugin +│ ├── Source/ +│ ├── Config/ +│ └── ThirdParty/ +├── Source/ +└── YourProject.uproject +``` + +Then regenerate your project files: + + + +```bash +# From your project root +/Users/Shared/Epic\ Games/UE_5.4/Engine/Build/BatchFiles/Mac/GenerateProjectFiles.sh \ + -project="$(pwd)/YourProject.uproject" -game -engine +``` + + +```powershell +# From your project root +& "C:\Program Files\Epic Games\UE_5.4\Engine\Build\BatchFiles\GenerateProjectFiles.bat" ^ + -project="%cd%\YourProject.uproject" -game -engine +``` + + + +--- + +## Add Module Dependency + +In your game module's `.Build.cs` file, add the `CometChat` module as a dependency: + +```csharp +using UnrealBuildTool; + +public class YourGame : ModuleRules +{ + public YourGame(ReadOnlyTargetRules Target) : base(Target) + { + PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; + + PublicDependencyModuleNames.AddRange(new string[] + { + "Core", + "CoreUObject", + "Engine", + "CometChat" // Add this line + }); + } +} +``` + +--- + +## Verify the Plugin + +After regenerating project files and building: + +1. Open your project in the Unreal Editor +2. Go to **Edit → Plugins** +3. Search for **CometChat** — it should appear under the **Networking** category and be enabled + + +The plugin loads at the **PreDefault** phase, so it's available before your game module initializes. + + +--- + +## Initialize CometChat + +The `CometChatSubsystem` is a `UGameInstanceSubsystem` — it's created automatically when your game starts. You just need to call **Configure** with your App ID and Region before using any other SDK methods. + + + +1. In any Blueprint, get a reference to the **CometChat Subsystem** via `Get Game Instance` → `Get Subsystem` → select `CometChatSubsystem` +2. Call the **Configure** node with your **App ID** and **Region** + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| App Id | `FString` | Your CometChat App ID | +| Region | `FString` | Your app region (`us` or `eu`) | + + +```cpp +#include "CometChatSubsystem.h" + +void AMyActor::BeginPlay() +{ + Super::BeginPlay(); + + UCometChatSubsystem* Chat = GetGameInstance()->GetSubsystem(); + Chat->Configure(TEXT("YOUR_APP_ID"), TEXT("us")); +} +``` + + + + +**Configure must be called before Login.** Calling Login without configuring first will result in a failure callback. + + +Make sure you replace `YOUR_APP_ID` with your actual CometChat **App ID**. + +--- + +## Next Steps + +Now that the plugin is installed and configured, head to [Authentication](/sdk/unreal/authentication) to log in your first user. diff --git a/sdk/unreal/typing-indicators.mdx b/sdk/unreal/typing-indicators.mdx new file mode 100644 index 000000000..692418233 --- /dev/null +++ b/sdk/unreal/typing-indicators.mdx @@ -0,0 +1,73 @@ +--- +title: "Typing Indicators" +description: "Show real-time typing indicators when users are composing messages." +--- + +Typing indicators let you show a "user is typing..." animation in your chat UI. The CometChat Unreal SDK delivers these as real-time events through the `OnTypingChanged` delegate. + +--- + +## Listen for Typing Events + +Bind to the `OnTypingChanged` delegate on the Subsystem to receive typing start/stop notifications. + + + +1. Get a reference to the **CometChat Subsystem** +2. Drag off and search for **On Typing Changed** +3. Use **Bind Event** to connect it to a custom event +4. The custom event receives an `FCometChatTypingEvent` parameter + + +```cpp +void AMyActor::BeginPlay() +{ + Super::BeginPlay(); + + UCometChatSubsystem* Chat = GetGameInstance()->GetSubsystem(); + Chat->OnTypingChanged.AddDynamic(this, &AMyActor::HandleTyping); +} + +void AMyActor::HandleTyping(const FCometChatTypingEvent& Event) +{ + if (Event.bIsTyping) + { + // Show typing indicator for this user/conversation + ShowTypingBubble(Event.Uid, Event.ConversationId); + } + else + { + // Hide typing indicator + HideTypingBubble(Event.Uid, Event.ConversationId); + } +} +``` + + + +--- + +## FCometChatTypingEvent + +| Property | Type | Description | +| -------- | ---- | ----------- | +| `Uid` | `FString` | The user who started or stopped typing | +| `ConversationId` | `FString` | The conversation where typing is happening | +| `bIsTyping` | `bool` | `true` when the user starts typing, `false` when they stop | + + +**UI pattern**: When `bIsTyping` is `true`, show a typing animation (e.g., three bouncing dots). When `false`, hide it. Consider adding a timeout (e.g., 5 seconds) to auto-hide the indicator in case the stop event is missed. + + +--- + +## Next Steps + + + + Track when messages are delivered and read. + + + Monitor the WebSocket connection state. + + diff --git a/sdk/unreal/users.mdx b/sdk/unreal/users.mdx new file mode 100644 index 000000000..17b4d7031 --- /dev/null +++ b/sdk/unreal/users.mdx @@ -0,0 +1,130 @@ +--- +title: "Users" +description: "Fetch user profiles and track user presence in real time." +--- + +## Get User + +Retrieve a user's profile by their UID. + + + +Call the **Get User Async** node. + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| Uid | `FString` | The unique identifier of the user to fetch | + +**On Success** returns an `FCometChatUser`. + + +```cpp +#include "AsyncActions/CometChatGetUserAction.h" + +void AMyActor::FetchUser() +{ + auto* Action = UCometChatGetUserAction::GetUserAsync( + this, + TEXT("cometchat-uid-2") + ); + Action->OnSuccess.AddDynamic(this, &AMyActor::OnUserFetched); + Action->OnFailure.AddDynamic(this, &AMyActor::OnUserFetchFailed); + Action->Activate(); +} + +void AMyActor::OnUserFetched(const FCometChatUser& User) +{ + UE_LOG(LogTemp, Log, TEXT("User: %s (%s)"), *User.Name, *User.Status); +} + +void AMyActor::OnUserFetchFailed(const FString& Error) +{ + UE_LOG(LogTemp, Error, TEXT("Fetch user failed: %s"), *Error); +} +``` + + + +### FCometChatUser Properties + +| Property | Type | Description | +| -------- | ---- | ----------- | +| `Uid` | `FString` | Unique user identifier | +| `Name` | `FString` | Display name | +| `AvatarUrl` | `FString` | URL to the user's avatar image | +| `Status` | `FString` | Current status text | + +--- + +## User Presence + +Track when users come online, go offline, or go away by binding to the `OnPresenceChanged` delegate on the Subsystem. + + + +1. Get a reference to the **CometChat Subsystem** +2. Drag off and search for **On Presence Changed** +3. Use **Bind Event** to connect it to a custom event +4. The custom event receives an `FCometChatPresence` parameter + + +```cpp +void AMyActor::BeginPlay() +{ + Super::BeginPlay(); + + UCometChatSubsystem* Chat = GetGameInstance()->GetSubsystem(); + Chat->OnPresenceChanged.AddDynamic(this, &AMyActor::HandlePresence); +} + +void AMyActor::HandlePresence(const FCometChatPresence& Presence) +{ + switch (Presence.Status) + { + case ECometChatPresenceStatus::Online: + UE_LOG(LogTemp, Log, TEXT("%s is online"), *Presence.Uid); + break; + case ECometChatPresenceStatus::Offline: + UE_LOG(LogTemp, Log, TEXT("%s went offline"), *Presence.Uid); + break; + case ECometChatPresenceStatus::Away: + UE_LOG(LogTemp, Log, TEXT("%s is away"), *Presence.Uid); + break; + } +} +``` + + + +### FCometChatPresence Properties + +| Property | Type | Description | +| -------- | ---- | ----------- | +| `Uid` | `FString` | The user whose presence changed | +| `Status` | `ECometChatPresenceStatus` | `Online`, `Offline`, or `Away` | +| `LastActiveAt` | `int64` | Unix timestamp of the user's last activity | + +### ECometChatPresenceStatus + +| Value | Description | +| ----- | ----------- | +| `Online` | User is currently active | +| `Offline` | User is not connected | +| `Away` | User is connected but idle | + + +Use presence data to show green/gray status dots next to player names in your friends list or lobby UI. + + +--- + +## Next Steps + + + + Create, join, and manage groups. + + + All five real-time delegates in one place. + +