Skip to main content

Getting started

Overview

CurseForge for Studios gives your game a mod ecosystem you do not have to build or host. Players browse, install and update mods from inside your game. CurseForge runs the storefront, the content delivery, the moderation queue and the ownership records behind it.

This page is the whole integration in order, from the first decision to the moment a mod loads in your game. It is a map rather than a manual. Each step states what it involves and links to the page that covers it in full.

The work splits into two halves, and the first one is easy to underestimate. The first half is your own game: it has to be able to load third-party content at all, and you decide where that content sits on disk and at which moment your game reads it. Those are your decisions, and no SDK can make them for you. The second half is the SDK, which finds mods, downloads them, keeps them current, and tells your game which ones are safe to load.

Browsing and installing mods is the smallest useful milestone. Selling mods, following a player's mod list across their devices, keeping a multiplayer session on one mod set, and letting players publish their own content are separate layers you add afterwards, in any order you like.

Some capabilities are switched on per game by CurseForge rather than in your project. Plan a short conversation with us before you build against those.

Before you write any code

Three things need to be true before the SDK is any use to you.

PrerequisiteWhy it matters
Your game can load modsThe SDK puts content on disk and tells you what is there. It does not make your game read it. Whatever form your mods take, scripted behaviour, textures, or cooked Unreal content, your game needs the code to load them
Your game is registeredA game record gives you the game id and API key that scope every call. See Setting up your game
Gated capabilities are enabled for your gamePremium mods, subscriptions, Try Before You Buy and each authentication provider are enabled per game by CurseForge, not by a setting in your project. Email cfforstudios@overwolf.com

Two decisions are also yours, and both are easier to make now than to change later.

Where mods live on disk. Pick the directory, and pick the layout inside it. See Deciding how mods sit on disk below.

When your game loads them. Reading mods off disk at an arbitrary moment tends to break things. Pick a point where your game is already loading content: when the player starts play from the main menu, when a new world loads, or immediately before a match begins.

The integration path

Nine steps, in order. Steps 1 and 2 happen outside your Unreal project.

StepWhat it involvesCovered in
1. Add mod support to your gameYour own loading code for whatever your mods containYour codebase
2. Register your gameCreate the game record, collect the game id and API keySetting up your game
3. Install the pluginExtract to Plugins/cfcore, answer the rebuild prompt, enable it, add the module dependency for C++ projectsInstallation
4. Configure the settingsgameId, apiKey, modsDirectory and modsDirectoryMode at minimumInitialization and settings
5. Initialize the SDKBring it up once at startup, tear it down on shutdownInitialization and settings
6. Sign the player inOnly needed for some capabilities. See the step belowAuthentication
7. Let players find modsQuery the catalogue yourself, or ship the prebuilt browserBrowsing and discovery, Mod browser
8. Install a modStart an install, track progress, handle failureInstalling and managing mods
9. Load installed modsAsk the SDK what is installed, decide what is loadable, load itInstalling and managing mods
tip

Read Error handling alongside step 5 rather than after step 9. Every SDK operation is asynchronous and reports failure through one of two error types, and picking that up late means rewriting call sites.

1. Add mod support to your game

This is the part that is not about CurseForge. Your game needs to accept content it did not ship with, whether that is scripts, assets, cooked plugin content, or configuration. If your game cannot do that yet, the SDK has nothing to hand it.

2. Register your game

Create your game in the Developer Portal at console.curseforge.com. You get a game id and an API key, which together scope every call the SDK makes. This is also where you set up categories, classes and permitted platforms, and where per-game capabilities get switched on.

3. Install the plugin

The SDK ships as a source-only Unreal plugin, so every project compiles it locally on first load. Extract the contents of the release folder into Plugins/cfcore, not the folder itself, so you end up with Plugins/cfcore/cfcore.uplugin one level down.

Then reopen the project and accept the rebuild prompt. C++ projects also add cfcore as a module dependency. Blueprint-only projects follow the same path, and the rebuild still needs a working C++ toolchain on the machine that opens the project first.

Installing the plugin does not start the SDK. Nothing happens until you initialize it.

4. Configure the settings

Settings live on the CFCore page under Project Settings > Plugins, or you can build the settings struct in code. Four matter from the start: gameId and apiKey from step 2, modsDirectory for where mods go, and modsDirectoryMode for the layout inside it.

warning

Anything set in Project Settings is written to DefaultGame.ini and ships in plaintext, where a player can edit it. That is fine for the game id and API key. It is not fine for premium mod signing keys, which have code-level overrides for exactly this reason. See Monetization.

5. Initialize the SDK

Bring the SDK up once, early, and wait for it to finish before calling anything else. Sub-interface accessors return null before initialization, and every Blueprint node fails with an initialization error. Tear it down on shutdown so in-flight work is cancelled cleanly.

All SDK calls are made from the game thread, and every asynchronous result comes back on the game thread. Compression and disk work happen on their own threads so they do not block your game loop, but you never have to marshal a callback yourself.

#include <cfcore_context.h>
#include <editor/cfcore_bp_library.h>

using namespace cfcore;

void AMyGameMode::InitializeCurseForge() {
FCFCoreSettings settings = UCFCoreBPLibrary::MakeSettingsFromProjectConfig();

CFCoreContext::GetInstance()->Initialize(
settings,
ICFCore::FInitializeDelegate::CreateUObject(
this, &AMyGameMode::OnCFCoreInitialized));
}

void AMyGameMode::OnCFCoreInitialized(TOptional<FCFCoreError> opt_err) {
if (opt_err.IsSet()) {
UE_LOG(LogTemp, Error, TEXT("CFCore init failed: %s"),
*opt_err.GetValue().description);
}
}

Blueprint: get the CFCore Subsystem, feed it a Make Settings From Project Config struct, then call Initialize (pins Target, Settings, OnInitialized, OnError). Full field reference on Initialization and settings.

6. Sign the player in

Plenty of a mod integration works without a signed-in player. Browsing the catalogue and installing free mods do not need one. Authentication is required for anything tied to a person: subscriptions that follow them across devices, rating, reporting, buying premium mods, and publishing their own content.

The SDK supports silent sign-in on platforms that provide an identity (Steam, PlayStation Network, Xbox Live and others) and an email one-time code flow elsewhere. Each provider is enabled and configured per game in the Developer Portal. A silent sign-in creates an anonymous CurseForge user, which the player can later connect to a real CurseForge account.

#include <api/models/enums/external_auth_provider.h>
#include <api/models/external_auth_additional_info.h>

void AMyGameMode::SignInSilently(const FString& PlatformToken,
const FDateTime& TermsAcceptedAt) {
FExternalAuthAdditionalInfo AdditionalInfo;
AdditionalInfo.eulaAcceptTime = TermsAcceptedAt;

CFCoreContext::GetInstance()->Authentication()
->GenerateAuthTokenByExternalProvider(
ECFCoreExternalAuthProvider::Steam, // set per build target
PlatformToken,
AdditionalInfo,
ICFCoreAuthentication::FGenerateAuthTokenDelegate::CreateLambda(
[this](const TOptional<FCFCoreError>& OptErr) {
if (OptErr.IsSet()) { return; }
OnSignedIn();
}));
}

Blueprint: Generate Auth Token for an external provider, pins provider, external_token, additional_info, on_success, on_error. For the email path use Send Security Code Email, then Generate Auth Token from Email Code. Full flow on Authentication.

7. Let players find mods

Two options, and they are not exclusive. Query the catalogue yourself and build your own interface, which gives you full control of the presentation. Or add the cfcore_ui plugin, a prebuilt in-game browser that already covers search, mod pages, ratings, sign-in, purchasing and subscriptions.

Studios shipping a first integration usually start with the prebuilt browser and replace parts of it later.

#include <cfcore_context.h>
#include <api/cfcore_api.h>

void UMyModBrowser::RunSearch(const FString& InText) {
FCFCoreSearchModsFilter Filter;
Filter.searchFilter = InText;

FCFCoreApiRequestPagination Pagination;
Pagination.pageSize = 20;

cfcore::CFCoreContext::GetInstance()->Api()->SearchMods(
Filter, Pagination,
ICFCoreApi::FSearchModsDelegate::CreateUObject(
this, &UMyModBrowser::OnSearchModsComplete));
}

Blueprint: Search Mods Info, pins filter, pagination, on_results, on_error. Full filter reference on Browsing and discovery.

8. Install a mod

Hand the SDK a mod and it downloads, verifies and extracts it, reporting progress as it goes. Installs are cancellable, and updates run through the same path. Failure has its own error codes, including the ones you will actually hit in production: no disk space, no network, and a hash that does not match.

void UMyModManager::InstallLatest(const FCFCoreMod& Mod) {
cfcore::CFCoreContext::GetInstance()->Library()->Install(
Mod,
FFile(), // id == 0 means "install the latest file"
FInstallModAdditionalParams(),
cfcore::ICFCoreLibrary::FInstallProgressDelegate::CreateLambda(
[](const FLibraryProgress& Progress) {
// Progress.dataTransfer.progress is 0 to 100.
}),
cfcore::ICFCoreLibrary::FInstalledDelegate::CreateLambda(
[](const TOptional<FInstalledMod>& OptInstalled,
const TOptional<FCFCoreError>& OptError) {
if (OptError.IsSet()) { return; }
}));
}

Blueprint: Install Mod, pins mod, on_progress, on_installed, on_error. Use Install Mod Extended instead for tracking, throttling, dynamic content, or a specific file rather than the latest. Full reference on Installing and managing mods.

9. Load installed mods

Earlier you chose the point where your game reads mods from disk, for example when the player starts play, loads a new world, or right before a match begins. At that point, ask the SDK what is installed. Each installed mod carries what you need to decide whether to touch it:

FieldWhat to do with it
statusOnly load a mod whose status says it is ready. Pending means the install has not finished, and Invalid means the content is missing or was modified on disk
enabledThe player can turn a mod off without uninstalling it. Respect it
pathOnDiskWhere to load from, relative to your mods directory

Both return every installed mod for the current player, including ones still installing, which is exactly why you check status rather than assuming.

#include <cfcore_context.h>
#include <library/cfcore_library.h>

void UMyModLoader::LoadEnabledMods() {
cfcore::CFCoreContext::GetInstance()->Library()->GetInstalledMods(
cfcore::ICFCoreLibrary::FGetInstalledModsDelegate::CreateLambda(
[](const TArray<FInstalledMod>& InstalledMods) {
for (const FInstalledMod& Mod : InstalledMods) {
if (!Mod.enabled) { continue; }
if (Mod.status == EInstalledModStatus::Pending ||
Mod.status == EInstalledModStatus::Invalid) {
continue;
}
// Mount Mod.pathOnDisk, relative to your mods directory.
}
}));
}

Blueprint: Get Installed Mods, in the cfcore|Library category. Full status reference on Installing and managing mods.

Deciding how mods sit on disk

modsDirectoryMode picks the layout, and it is worth a minute of thought because changing it after players have mods installed is a migration.

ModeLayoutUse it when
CFCoreA folder per game, then a folder per mod and file revision, then the mod contents. The defaultAlmost always. The SDK owns the tree and can tell revisions apart
FlatMod contents sit directly in the mods directoryYour game or engine already requires a specific flat layout
warning

Pointing Flat at a folder your game already scans for mods gives up control. You lose the SDK's ability to distinguish an enabled mod from a disabled one, and a paid mod from an owned one, because anything in that folder looks installed to your own loading code. If you use Flat, keep it in a directory only the SDK writes to.

Before you ship

Three things are worth doing before a build reaches players.

Turn on the disk logger. The SDK logs through the standard Unreal logging macro, and most shipped builds do not persist those logs. The plugin can write its own log files instead, with a size cap and a retained history count. This is off by default. When a player cannot install a mod, these logs are what makes the problem diagnosable.

Decide your analytics categories. Performance and stability analytics are on by default and collected for you, covering install and update success rates across your mod ecosystem. User engagement analytics are off by default and are not collected automatically: you enable the category and call the reporting functions from your own code. See Analytics.

Check what the backend has enabled. Your game can read its own enabled feature set at runtime rather than assuming. That is the reliable way to confirm a capability is live for your game before you show a button for it. See Game info and platforms.

What you add next

Each of these is independent. Add them in whatever order matches your roadmap.

CapabilityWhat it addsPage
Mod dependenciesHandling mods that require, prefer or conflict with other mods. The SDK reports the relationships and your game decides what to doMod dependencies
SubscriptionsA player's mod list follows them to any device running your gameSubscriptions
Multiplayer and serversEvery participant in a session ends up on the same mod set, including a check that they own the paid onesMultiplayer and servers
MonetizationSelling individual mods, with discounts and time-limited trialsMonetization
Creating UGCPlayers publish and update their own mods, either from your game or from your editorCreating UGC
Ratings, reporting and blockingWhat a signed-in player does to a mod besides installing itRatings, reporting and blocking

For the shape of the SDK itself, the module layout and the two development interfaces, read Overview. For a per-page summary of everything in this section, read In this section.

Getting help

For integration questions, SDK access, or to have a capability enabled for your game, contact cfforstudios@overwolf.com. Game and content configuration is in the Developer Portal at console.curseforge.com.