# Workshop

{% embed url="<https://partner.steamgames.com/doc/features/workshop>" %}

> The Steam Workshop is designed as a place for your fans and community members to participate in the creation of content for your game. The form of this creation by community members can vary depending on the nature of the game and what kind of control you wish to have over the content in your game.

There are steps you need to take in the Steam Developer Portal to enable Steam Workshop for your game. Be sure you have read Valve's implementation guide and followed its instructions.

{% embed url="<https://partner.steamgames.com/doc/features/workshop/implementation#EnableISteamUGC>" %}

The following is a snip-it from the above-linked document. Be sure you do read the original document first; this is here as a quick reference only.

## Enabling UGC for a Game or Application

Before workshop items can be uploaded to the Steamworks backend, two configuration settings must be made: Configuring Steam Cloud Quotas and Enabling the UGC API.\
\
The Steam Cloud feature is used to store the preview images associated with workshop items. The Steam Cloud Quota can be configured with the following steps:<br>

1. Navigate to the [Steam Cloud Settings](https://partner.steamgames.com/apps/cloud/) page in the App Admin panel.
2. Set the **Byte quota per user** and the **Number of files allowed per user** to appropriate values for preview image storage
3. Click Save
4. From the **Publish** tab, click **Prepare for Publishing**
5. Click **Publish to Steam** and complete the process to publish the change.

\
Enabling the UGC API can be accomplished with the following steps:<br>

1. You can just navigate to the [Steam Workshop Configuration](https://partner.steamgames.com/apps/workshop/) page in the App Admin panel.
2. Find the **Additional Configuration Options** section.
3. Check **Enable ISteamUGC for file transfer**.
4. Click **Save**.
5. From the **Publish** tab, click **Prepare for Publishing**.
6. Click **Publish to Steam** and complete the process to publish the change.

Once these settings are in place, workshop content can be uploaded via the API.

## Working with UGC

<figure><img src="https://3622319385-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkfE3ZAs6TeNW5sBM2C3i%2Fuploads%2FvIP35XpzXE8zZXDokzuB%2Fimage.png?alt=media&#x26;token=c9d2726f-bdba-43c5-a7cc-b9001477f2cc" alt="Image for reference find the original at https://partner.steamgames.com/doc/features/workshop/implementation#CreateUploadContent"><figcaption><p>Image for reference only, find the original at <a href="https://partner.steamgames.com/doc/features/workshop/implementation#CreateUploadContent">https://partner.steamgames.com/doc/features/workshop/implementation#CreateUploadContent</a></p></figcaption></figure>

The process of uploading content to UGC is a simple 2-step process.

### Create an Item

Using our tools, you will create a new empty item; this will provide you with a Published File handle that can be used in the second step.

### Updating an Item

This process lets you update an existing Published File. You do this by calling "Start Update", which provides you with an update handle. You can then set each field of the item, such as Name, Description, Preview Image, and so on, and finalise the update with Submit item update.

## Examples

### Create Item

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

## Code Free

You can use the Workshop Item Editor to power in-game Workshop tools..

<figure><img src="https://3622319385-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkfE3ZAs6TeNW5sBM2C3i%2Fuploads%2FQux2rPbbXrizKOrjIIMI%2Fimage.png?alt=media&#x26;token=7d6528b5-f608-46aa-acf8-9027a3e88e55" alt=""><figcaption></figcaption></figure>

The base editor defines the minimal required fields which can be connected to Input Fields for user or code-based population.

<figure><img src="https://3622319385-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkfE3ZAs6TeNW5sBM2C3i%2Fuploads%2FobgBYuPoK1DrFk1BT5Wh%2Fimage.png?alt=media&#x26;token=cf2d24e8-1d77-40eb-9f42-c4df0a436fb2" alt=""><figcaption></figcaption></figure>

Add the Create & Update settings to expand with optional data, use the Create New or Create and Update functions to submit the item to Steam.

<figure><img src="https://3622319385-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkfE3ZAs6TeNW5sBM2C3i%2Fuploads%2FLJNCvo9NuUBGHIHCLqkH%2Fimage.png?alt=media&#x26;token=45eb224b-3fee-48b5-a757-1e095509b126" alt=""><figcaption></figcaption></figure>

Add the Events settings to expose key events to help drive your editor UI&#x20;

<figure><img src="https://3622319385-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkfE3ZAs6TeNW5sBM2C3i%2Fuploads%2FlmEgMY9ZPUlWBCRiTVQt%2Fimage.png?alt=media&#x26;token=3e9f5f7b-5e8b-4586-a99b-668b6ca7362b" alt=""><figcaption></figcaption></figure>

## C\#

```csharp
// Use the Workshop Item Editor Data to build up your item
WorkshopItemEditorData data = new();
data.title = "New Item";
data.description = "My first workshop item";
data.content = new("C:\\MyModContent");
data.preview = new("C:\\MyModPreviewImage.png");
data.visibility = ERemoteStoragePublishedFileVisibility.k_ERemoteStoragePublishedFileVisibilityPrivate;

// Now you can create and update the item
// each callback is optional, but you should at least
// use HandleCompletion
data.Create(HandleCompletion, HandleUpdateStarted, HandleNewItemCreated);

public void HandleNewItemCreated(CreateItemResult createResult)
{
    // Invoked after the new file ID has been created, but before it
    // has had all its values set
}

public void HandleUpdateStarted(UGCUpdateHandle_t updateHandle)
{
    // Invoked when the update handle is created
    // This happens just before setting the title, description, etc.
}

public void HandleCompletion(WorkshopItemDataCreateStatus status)
{
    // Always invoked even if a failure occurred.
    // This will tell you the results of the create and update.
    // This is only invoked after all other steps are completed.
}
```

{% endtab %}

{% tab title="Toolkit for Unreal" %}

## Blueprint

Note this creates an empty file ID that you can then update to add the desired content.

<figure><img src="https://3622319385-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkfE3ZAs6TeNW5sBM2C3i%2Fuploads%2FrhVyPOewBsXbWc6bylsP%2Fimage.png?alt=media&#x26;token=34c53aab-5614-4bb0-8d86-0716d7f4f034" alt=""><figcaption></figcaption></figure>

## C++

```cpp
Coming Soon
```

{% endtab %}

{% tab title="Steamworks.NET" %}

{% endtab %}
{% endtabs %}

### Update Item

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

## Code Free

Use the Workshop Item Search to get the items that the player has published.&#x20;

{% hint style="info" %}
See the [List Items](#list-items) example below\..
{% endhint %}

You can use the Search My Published function to get all of the items published by the player.

<figure><img src="https://3622319385-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkfE3ZAs6TeNW5sBM2C3i%2Fuploads%2FRYGQFzTLx2FHek7UzklN%2Fimage.png?alt=media&#x26;token=7ef8ffc3-40b7-410b-9cf9-72baac00b993" alt=""><figcaption></figcaption></figure>

In the Workshop Item component in your Workshop Item Search template, add the Edit settings. Note that this will automatically add the Events settings

<figure><img src="https://3622319385-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkfE3ZAs6TeNW5sBM2C3i%2Fuploads%2FdiSKORiwQKjYr66aX499%2Fimage.png?alt=media&#x26;token=cf52c2cb-ebd8-4e4a-95b4-18d7112d44c3" alt=""><figcaption></figcaption></figure>

You can attach input fields for quick edits to modify the title, description, content folder, etc., or you can pass the item a Workshop Item Editor for a more robust set of features.

<figure><img src="https://3622319385-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkfE3ZAs6TeNW5sBM2C3i%2Fuploads%2FWK6rYtjdyRSTN1nZTzah%2Fimage.png?alt=media&#x26;token=ed988667-09e3-4840-94d2-c984fbf6f2af" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3622319385-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkfE3ZAs6TeNW5sBM2C3i%2Fuploads%2F4O2uQo3Js5fyPFfzIRzo%2Fimage.png?alt=media&#x26;token=de1eafee-2b06-4177-a695-da180036c3b8" alt=""><figcaption></figcaption></figure>

Running the Set Editor function will load this item into the editor's memory. Note that the preview image and content folder path can't be loaded, so you will need to make sure you set those values yourself via an input field or a file/folder browser.

## C\#

This works similarly to [Create Item](#create-item) as defined above, with 1 minor difference ... call Update instead of Create.

```csharp
// Use the Workshop Item Editor Data to build up your item
WorkshopItemEditorData data = new();
data.title = "New Item";
data.description = "My first workshop item";
data.content = new("C:\\MyModContent");
data.preview = new("C:\\MyModPreviewImage.png");

// Call update when ready
data.Update(HandleCompleted, HandleUpdateStarted);
```

{% endtab %}

{% tab title="Toolkit for Unreal" %}

## Blueprint

Using a Published File ID such as from the Create Item process

<figure><img src="https://3622319385-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkfE3ZAs6TeNW5sBM2C3i%2Fuploads%2FVA6HWAipfSIuN6YjFKP0%2Fimage.png?alt=media&#x26;token=f40ee535-bc65-4aea-93f3-fef8fa063678" alt=""><figcaption></figcaption></figure>

You can then use the "Set Item" nodes to update each aspect of the item.

<figure><img src="https://3622319385-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkfE3ZAs6TeNW5sBM2C3i%2Fuploads%2F4ZrT0zCPFSDszrDMzeiB%2Fimage.png?alt=media&#x26;token=e6c4855e-e08c-4f5a-9c64-94eb83379b85" alt=""><figcaption></figcaption></figure>

The following nodes are required for all items

<figure><img src="https://3622319385-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkfE3ZAs6TeNW5sBM2C3i%2Fuploads%2FjalOkKUmR0FSQ1xleWhp%2Fimage.png?alt=media&#x26;token=30a978de-5885-49e9-a8e3-4f2670998866" alt=""><figcaption></figcaption></figure>

## C++

```cpp
Coming Soon
```

{% endtab %}

{% tab title="Steamworks.NET" %}

{% endtab %}
{% endtabs %}

### List Items

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

## Code Free

Use the Workshop Item Search component to search for workshop items

<figure><img src="https://3622319385-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkfE3ZAs6TeNW5sBM2C3i%2Fuploads%2F0AiFDCp1kW2RQJ0oJ6d8%2Fimage.png?alt=media&#x26;token=5f234d65-aa39-492c-9ab4-253b97a2f8cb" alt=""><figcaption></figcaption></figure>

The key and only "required" features are:

### Template

This is the object that will be spawned for each item returned by your search. This would be a Unity UI prefab that has a Workshop Item component on it, helping you "display" each of the items.

### Content

This is where each item will be parented when it's spawned. Typically, you would apply a "Layout" component to this, such as Unity's built-in Grid Layout component.

### Setting up the Workshop Item

The Workshop Item component is what you attach to your "Template" to connect data from the workshop item to your UI elements.

<figure><img src="https://3622319385-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkfE3ZAs6TeNW5sBM2C3i%2Fuploads%2FlKyKYAiQpXPFDJD5aiQP%2Fimage.png?alt=media&#x26;token=e122654a-8fd1-4b9f-b205-0f91bde1af46" alt=""><figcaption></figcaption></figure>

This is a modular component, so you can add as much or as little functionality as you need for your UI.

<figure><img src="https://3622319385-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkfE3ZAs6TeNW5sBM2C3i%2Fuploads%2FWOM3LL43rePY7ojl7Iap%2Fimage.png?alt=media&#x26;token=290813f1-45c6-47e0-84ee-c5bed0b736d8" alt=""><figcaption></figcaption></figure>

We have a prefab called "Workshop Item Search" that demonstrates this complete system, and that prefab is used in our sample scene. Consult the [installation guide](https://kb.heathen.group/steam/install/unity-install) for more information on how to find the prefabs and samples.

When you're ready to run the search, use a Unity Button or similar and call one of the "Search" functions.

<figure><img src="https://3622319385-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkfE3ZAs6TeNW5sBM2C3i%2Fuploads%2Fsu8S6RFP1Pw0AYUCYhid%2Fimage.png?alt=media&#x26;token=d54fc9d6-5fbc-4c7c-abe4-e5b84c2ce37c" alt=""><figcaption></figcaption></figure>

Options include:

* Search All\
  Returns any item found, similar to browsing in the Workshop page on Steam
* Search Favorites\
  Returns only items the player has favourited
* Search My Published\
  Returns only items the player has created
* Search Subscribed\
  Returns only items the player has subscribed to, e.g. "installed"

## C\#

<pre class="language-csharp"><code class="lang-csharp">// Create a query to find the desired items
var query = UgcQuery.Get(EUGCQuery.k_EUGCQuery_RankedByTrend
    , EUGCMatchingUGCType.k_EUGCMatchingUGCType_Items_ReadyToUse
    , AppData.Me
    , AppData.Me);
    
// Optionally filter on a search string
query.SetSearchText("Text to search");

<strong>// Run the query
</strong>query.Execute(HandleResults);

// Handle the results
void HandleResults(UgcQuery query)
{
    // Iterate over the found items
    foreach (var result in query.ResultsList)
    {
        // Do something with it
    }
}
</code></pre>

{% endtab %}

{% tab title="Toolkit for Unreal" %}

## Blueprint

### Subscribed Items

You can quickly get the items the player is subscribed to e.g. are using in-game via

<figure><img src="https://3622319385-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkfE3ZAs6TeNW5sBM2C3i%2Fuploads%2FE7pPAfucxaRrI0SVZDwf%2Fimage.png?alt=media&#x26;token=d0b6ae3b-1945-4dbe-959f-882d673e71da" alt=""><figcaption></figcaption></figure>

This will result in a Query Handle as with general queries but it is not "paged" meaning all items will return in a single execute.

### General Queries

<figure><img src="https://3622319385-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkfE3ZAs6TeNW5sBM2C3i%2Fuploads%2FKnp3IgLNKoaY4yuqVbFF%2Fimage.png?alt=media&#x26;token=e9da0ee0-7568-4496-b941-196812ce197f" alt=""><figcaption></figcaption></figure>

#### Account ID

Account ID refers to the account ID of the user you want to get items for. You can obtain the account ID of a Steam User from their user ID.

<figure><img src="https://3622319385-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkfE3ZAs6TeNW5sBM2C3i%2Fuploads%2FqxiLjdygsp6lMOwKxzPN%2Fimage.png?alt=media&#x26;token=28a8d2c0-da40-4455-a190-a59cfd57b717" alt=""><figcaption></figcaption></figure>

### Configure the Query

By default a query will return minimal informaiton generally the title, short description and install path and state. You can request additional data be returned using the "Set Return" nodes.

<figure><img src="https://3622319385-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkfE3ZAs6TeNW5sBM2C3i%2Fuploads%2FwIrvHKyyZ8U6dh8ZoWb5%2Fimage.png?alt=media&#x26;token=01230320-51b6-4c7e-b399-a219bc7ff696" alt=""><figcaption></figcaption></figure>

### Execute Query

<figure><img src="https://3622319385-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkfE3ZAs6TeNW5sBM2C3i%2Fuploads%2FTIxdlNMwb9FNxaGcx36L%2Fimage.png?alt=media&#x26;token=abf905f2-dd8a-4d28-a294-f297874c55d8" alt=""><figcaption></figcaption></figure>

When you execute a query you are provided with the number of results returned and the total number of results matching the query.

Each page is 50 results so you can assume the total number of pages is TotalMatchingResults / 50 + 1

### Reading Results

<figure><img src="https://3622319385-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkfE3ZAs6TeNW5sBM2C3i%2Fuploads%2FUXPC6iVk03wTCpA7pG2g%2Fimage.png?alt=media&#x26;token=0f73d62d-648a-4ebc-b3dc-6a7de5faf1d0" alt=""><figcaption></figcaption></figure>

The return value contains all the details about each item, note that some fields like metadata and tags may not populate unless you request them with the "Set Return" feature.

<figure><img src="https://3622319385-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkfE3ZAs6TeNW5sBM2C3i%2Fuploads%2F8078h4S9hGmCbNmmcgvl%2Fimage.png?alt=media&#x26;token=0a76f7f8-f5c4-4b00-a36c-eccb2db96a98" alt=""><figcaption></figcaption></figure>

When complete and before creating another query, release the handle

<figure><img src="https://3622319385-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkfE3ZAs6TeNW5sBM2C3i%2Fuploads%2FmlRdaD1csyFrSPDK9XcW%2Fimage.png?alt=media&#x26;token=3364b1d5-1646-4b6f-af86-583a4644b243" alt=""><figcaption></figcaption></figure>

## C++

```cpp
Coming Soon
```

{% endtab %}

{% tab title="Steamworks.NET" %}

{% endtab %}
{% endtabs %}

### Find Installed Content

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

## Code Free&#x20;

You can find the items the player has installed by using the "Search Subscribed" option when [listing items](#list-items). Accessing the content it downloaded however will require C# code and is up to your programmer to do.

## C\#

```csharp
// Get a query for the subscribed items
var query = UgcQuery.GetSubscribed();
// Run the query
query.Execute(HandleResults);

// Handle the results
void HandleResults(UgcQuery query)
{
    // Iterate over the found items
    foreach (var result in query.ResultsList)
    {
        // Check if its installed and download if needed
        if (!result.IsInstalled)
            result.DownloadItem(true);
        
        // Check if this item is downloading or going to download
        if (result.IsDownloading
           || result.IsDownloadPending)
            ;// handle download in progress

        // Monitor how much is downloaded
        float percentComplete = result.DownloadCompletion;

        // The location where the content is downloaded to
        result.FolderPath
    }
}
```

{% endtab %}

{% tab title="Toolkit for Unreal" %}

## Blueprint

<figure><img src="https://3622319385-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkfE3ZAs6TeNW5sBM2C3i%2Fuploads%2FHXvk88M5jahC01mN1p9J%2Fimage.png?alt=media&#x26;token=a4a24372-522b-4731-9107-91f7aa42fdbd" alt=""><figcaption></figcaption></figure>

## C++

```cpp
Coming Soon
```

{% endtab %}

{% tab title="Steamworks.NET" %}

{% endtab %}
{% endtabs %}
