# List Broadcasts In-Game

In this How-to, we will start a session with the users timezone, retrieve the latest broadcast messages and display the data in your engine.

## Prerequisites

* [A LootLocker account and a created game](https://lootlocker.com/sign-up)
* [The LootLocker SDK configured and implemented in your game](https://docs.lootlocker.com/the-basics/sdks)
* [Configured broadcasts in the Web Console](https://docs.lootlocker.com/players/broadcasts/how-to/configure-broadcasts-in-web-console)

## Start Session with Timezone Support (Optional)

To ensure broadcast messages are filtered and scheduled according to the players timezone, you can optionally include timezone information when starting a player session.

In this How-To, we are using [Guest Login](https://docs.lootlocker.com/players/authentication/how-to/guest-login), but [all platforms](https://docs.lootlocker.com/players/authentication) are supported.

{% tabs %}
{% tab title="Unity" %}

```csharp
using LootLocker.Requests;
using System;

public void StartSessionWithTimezone()
{
    // Create session optionals to include timezone
    LootLockerSessionOptionals optionals = new LootLockerSessionOptionals();
    
    // For Windows, convert the system timezone to IANA format, read more in the section below
    optionals.timezone = LootLockerTimezoneConverter.ConvertWindowsToIanaTzString(TimeZoneInfo.Local.StandardName);
    
    // Start a guest session with timezone
    LootLockerSDKManager.StartGuestSession((response) =>
    {
        if (response.success)
        {
            Debug.Log("Session started successfully with timezone: " + options.timezone);
            // Proceed to retrieve broadcasts
        }
        else
        {
            Debug.LogError("Failed to start session: " + response.errorData.message);
        }
    }, optionals);
}
```

{% endtab %}

{% tab title="Unreal C++" %}

```cpp
#include "LootLockerSDKManager.h"

void YourClass::StartSessionWithTimezone()
{
	FLootLockerSessionOptionals optionals {
		YourClass::GetTimezone()
	};
	ULootLockerSDKManager::GuestLogin(FLootLockerSessionResponse::CreateLambda([](FLootLockerAuthenticationResponse Response) {
		if (Response.success) {
			UE_LOG(LogWorkingProject, Display, TEXT("Session started successfully with timezone! Player ULID: %s"), *Response.player_ulid);
		} else {
			UE_LOG(LogWorkingProject, Error, TEXT("Failed to start session with timezone: %s"), *Response.ErrorData.Message);
		}
	}), "", optionals);
}
```

{% endtab %}

{% tab title="Unreal Blueprints" %}

<figure><img src="https://534367586-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MVu1MPzezO-NgvC98xh%2Fuploads%2Fgit-blob-c4668b3ff965de2a11b8fc4d44c6bde92e8325a8%2Funreal-blueprint-start-session-with-timezone.png?alt=media" alt=""><figcaption><p><a href="https://blueprintue.com/blueprint/5i2h8m-5/">Blueprint example of starting a LootLocker session with a timezone optional</a></p></figcaption></figure>
{% endtab %}

{% tab title="REST" %}

### Coming Soon

{% endtab %}
{% endtabs %}

## About Timezones

LootLocker uses the [Iana](https://www.iana.org/time-zones) standard for dealing with timezones. A timezone is written to a players [metadata](https://docs.lootlocker.com/shared-systems/metadata) with the key `ll.timezone`.

All platforms *except* Windows uses [Iana](https://www.iana.org/time-zones). If your game is running on Windows, you **must** convert the Windows timezone to an Iana timezone before sending it to LootLocker.

{% tabs %}
{% tab title="Unity" %}
Use the utility-class `LootLockerTimezoneConverter` to convert back and forth between Iana timezones

```csharp
    // When sending a Windows Timezone to LootLocker:
        LootLockerTimezoneConverter.TryConvertStringToIanaTzString(TimeZoneInfo.Local.StandardName);
    // When reading an Iana timezone returned from LootLocker:
        LootLockerTimezoneConverter.TryConvertStringToWindowsTzString(/*LootLockerIanaTimezoneReturnedFromMetadata*/);
```

{% endtab %}

{% tab title="Unreal C++" %}
Every time you start a LootLocker session, send the Iana timezone for the user. One way to do this is to calculate the offset from UTC and format it as an Iana timezone:

```cpp
FString YourClass::GetCurrentUTCOffsetAsIanaTimezone()
{
	FDateTime Now = FDateTime::Now();
	FDateTime UTCNow = FDateTime::UtcNow();
	FTimespan Offset = Now - UTCNow;
	int offsetHours = Offset.GetHours();
	FString tz = FString::Printf(TEXT("ETC/GMT%s%d"), offsetHours < 0 ? TEXT("-") : TEXT("+"), FMath::Abs(offsetHours));
	return tz.IsEmpty() ? TEXT("N/A") : tz;
}
```

{% endtab %}

{% tab title="Unreal Blueprints" %}
Every time you start a LootLocker session, send the Iana timezone for the user. One way to do this is to calculate the offset from UTC and format it as an Iana timezone:

<figure><img src="https://534367586-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MVu1MPzezO-NgvC98xh%2Fuploads%2Fgit-blob-0140ebda7cc2f0c72e62ad07366816a806ac3f09%2Fiana-tz-from-utc-offset.png?alt=media" alt=""><figcaption><p><a href="https://blueprintue.com/blueprint/n2gmd0v3/">Blueprint example of creating an Iana offset timezone code from calculated UTC offset</a></p></figcaption></figure>
{% endtab %}
{% endtabs %}

## Retrieve Broadcast Messages

Once you have an active session, you can retrieve broadcast messages that are currently live for your game and display the information in regards to the users preferred language,

{% tabs %}
{% tab title="Unity" %}

```csharp
using LootLocker.Requests;
using System.Collections.Generic;

public void GetBroadcastMessages()
{
    string[] languagesToRetrieve = new string[] { "en", "sv" }; // English and Swedish
    int limit = 10; // Number of items to fetch in this request
    
    LootLockerSDKManager.ListBroadcasts(languagesToRetrieve, limit, (response) =>
    {
        if (response.success)
        {
            Debug.Log($"Retrieved {response.broadcasts.Length} broadcast messages");
            
            foreach (var broadcast in response.broadcasts)
            {
                ProcessBroadcast(broadcast);
            }
        }
        else
        {
            Debug.LogError("Failed to retrieve broadcasts: " + response.errorData.message);
        }
    });
}

// Example function for processing the broadcast
private void ProcessBroadcast(BroadcastMessage broadcast)
{
    // If you need to treat languages differently, you can check the key of the current language
    if (broadcast.languages.ContainsKey("en"))
    {
        LootLockerBroadcastLanguage currentLanguage = broadcast.languages["en"];
        // The headline of the broadcast
        Debug.Log($"Headline: {currentLanguage.headline}");
        // The body of the broadcast
        Debug.Log($"Body: {currentLanguage.body}");
        // The language code of the broadcast
        Debug.Log($"Language: {currentLanguage.language_code}");
        // An URL to an image, add your own logic to download and display images in your UI
        Debug.Log($"Image URL: {currentLanguage.image_url}");
        // Custom action to take, for example starting a specific animation or instantiate a certain prefab
        Debug.Log($"Action: {currentLanguage.action}");
        // Process additional logic for extra localization keys, if any
        foreach (var extraLocalization in currentLanguage.localizations)
        {
            Debug.Log($"Additional Localization - Key: {extraLocalization.Key}, Value: {extraLocalization.Value}");
        }
    }
}
```

{% endtab %}

{% tab title="Unreal C++" %}

```cpp
#include "LootLockerSDKManager.h"

void YourClass::ListBroadcasts()
{
	TArray<FString> LanguagesToRetrieve { "en", "sv" }; // English and Swedish
	int Limit = 10; // Number of items to fetch in this request
    
	ULootLockerSDKManager::ListBroadcasts(LanguagesToRetrieve, Limit, FLootLockerListBroadcastsResponseDelegate::CreateLambda([](const FLootLockerListBroadcastsResponse& Response)
    {
        if (Response.success)
        {
            for (const FLootLockerBroadcast& broadcast : Response.broadcasts)
            {

                UE_LOG(YOUR_LOG_CATEGORY, Display, TEXT("Broadcast ID: %s"), *broadcast.id);
                UE_LOG(YOUR_LOG_CATEGORY, Display, TEXT("Broadcast Name: %s"), *broadcast.name);
                UE_LOG(YOUR_LOG_CATEGORY, Display, TEXT("Game Name: %s"), *broadcast.game_name);
                UE_LOG(YOUR_LOG_CATEGORY, Display, TEXT("Publication information:"));
                for(const FLootLockerBroadcastPublicationSetting& publicationSettings : broadcast.publication_settings)
                {
                    UE_LOG(YOUR_LOG_CATEGORY, Display, TEXT("    Publication Setting ID: %d"), publicationSettings.id);
                    UE_LOG(YOUR_LOG_CATEGORY, Display, TEXT("    Publication start date: %s"), *publicationSettings.start.ToString());
                    UE_LOG(YOUR_LOG_CATEGORY, Display, TEXT("    Publication end date: %s"), *publicationSettings.end.ToString());
                    UE_LOG(YOUR_LOG_CATEGORY, Display, TEXT("    Publication timezone: %s"), *publicationSettings.tz);
                }

                // If you need to treat languages differently, you can check the key of the current language
                if(broadcast.languages.Contains("en")) {
                    const FLootLockerBroadcastLanguage& currentLanguage = broadcast.languages["en"];
                    UE_LOG(YOUR_LOG_CATEGORY, Display, TEXT("Headline: %s"), *currentLanguage.headline);
                    UE_LOG(YOUR_LOG_CATEGORY, Display, TEXT("Body: %s"), *currentLanguage.body);
                    UE_LOG(YOUR_LOG_CATEGORY, Display, TEXT("Language code: %s"), *currentLanguage.language_code);
                    UE_LOG(YOUR_LOG_CATEGORY, Display, TEXT("Image URL: %s"), *currentLanguage.image_url);
                    UE_LOG(YOUR_LOG_CATEGORY, Display, TEXT("Action: %s"), *currentLanguage.action);
                    for(const auto& extraLocalization : currentLanguage.localizations) {
                        UE_LOG(YOUR_LOG_CATEGORY, Display, TEXT("Additional Localization - Key: %s, Value: %s"), *extraLocalization.Key, *extraLocalization.Value);
                    }
                }
            }
        }
        else
        {
            UE_LOG(YOUR_LOG_CATEGORY, Error, TEXT("ListBroadcasts failed: %s"), *Response.ErrorData.Message);
        }
    }));
}
```

{% endtab %}

{% tab title="Unreal Blueprints" %}

<figure><img src="https://534367586-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MVu1MPzezO-NgvC98xh%2Fuploads%2Fgit-blob-acbc342995a112c74e3f592b4237d23bd7e8701d%2Funreal-blueprint-list-broadcasts.png?alt=media" alt=""><figcaption><p><a href="https://blueprintue.com/blueprint/a5_5dmom/">Blueprint example of listing Broadcasts</a></p></figcaption></figure>
{% endtab %}

{% tab title="REST" %}

### Coming Soon

{% endtab %}
{% endtabs %}

## Conclusion

In this How-to, we successfully completed the task of retrieving broadcast messages from LootLocker and have displayed their information.

With this implementation, your game can now retrieve rich, localized broadcast messages that are properly scheduled according to player timezones. The multiple localization support allows you to access content in different languages and include custom localized fields like button text, subtitles, and other game-specific content.
