Skip to main content

Overview

CurseForge is one of the largest mod hosting platforms for Minecraft and other games. MCReleaser provides comprehensive integration with CurseForge’s API, supporting both Minecraft and Hytale projects with full version metadata including game versions, mod loaders, Java versions, and environment specifications. The platform automatically fetches and resolves game version IDs from CurseForge’s API, ensuring your releases are properly tagged with all necessary metadata.

Required Credentials

To publish to CurseForge, you need:
  1. CurseForge API Token: An API token from your CurseForge account
  2. Project ID: The numeric project ID from your project page
Create a CurseForge API token at console.curseforge.com. Make sure it has upload permissions for your project.

Configuration Options

CURSEFORGE_TOKEN
string
required
The CurseForge API token for authentication.
-e CURSEFORGE_TOKEN="your_token_here"
CURSEFORGE_PROJECT
string
required
The numeric project ID. You can find this on your project’s page or in the URL.Example: 123456
-e CURSEFORGE_PROJECT="123456"
CURSEFORGE_TYPE
string
default:"minecraft"
The game type for your project.Valid values:
  • minecraft - For Minecraft mods and plugins
  • hytale - For Hytale mods (legacy support)
-e CURSEFORGE_TYPE="minecraft"
CURSEFORGE_RELEASE_TYPE
string
default:"release"
The type of release.Valid values:
  • release - Stable release
  • beta - Beta version
  • alpha - Alpha version
-e CURSEFORGE_RELEASE_TYPE="release"
CURSEFORGE_GAME_VERSIONS
string
Space-separated list of Minecraft versions that your mod supports.MCReleaser will automatically resolve these to CurseForge’s game version IDs.Examples:
# Specific versions
-e CURSEFORGE_GAME_VERSIONS="1.20.1 1.20.2 1.20.4"

# Version range
-e CURSEFORGE_GAME_VERSIONS="1.19-1.20.4"
If not set, falls back to the common GAME_VERSIONS variable.
CURSEFORGE_MOD_LOADERS
string
Space-separated list of mod loaders.Common loaders: forge, fabric, quilt, neoforgeExample:
-e CURSEFORGE_MOD_LOADERS="forge fabric"
MCReleaser will automatically resolve loader names to CurseForge’s version IDs.
CURSEFORGE_JAVA_VERSION
string
The Java version required for your mod.Just specify the version number, MCReleaser will format it as needed.Example:
# For Java 17
-e CURSEFORGE_JAVA_VERSION="17"

# For Java 21
-e CURSEFORGE_JAVA_VERSION="21"
CURSEFORGE_ENVIRONMENT
string
Space-separated list of supported environments.Valid values: client, serverExamples:
# Client and server
-e CURSEFORGE_ENVIRONMENT="client server"

# Client only
-e CURSEFORGE_ENVIRONMENT="client"
CURSEFORGE_RELATIONS
string
JSON array of project dependencies and relations.Each relation specifies a project slug and the relation type.Example:
[
  {
    "slug": "jei",
    "type": "requiredDependency"
  },
  {
    "slug": "cloth-config",
    "type": "optionalDependency"
  },
  {
    "slug": "optifine",
    "type": "incompatible"
  }
]
Relation types:
  • requiredDependency - Required to run
  • optionalDependency - Optional enhancement
  • incompatible - Cannot be used together
  • embeddedLibrary - Bundled inside your mod
CURSEFORGE_MANUAL
boolean
Whether to create the release as manual (not auto-published).When true, the version will be created but not automatically published, allowing you to review it first.
-e CURSEFORGE_MANUAL="true"

Implementation Details

The CurseForge platform implementation performs the following steps:
  1. Version Type Resolution: Fetches game version types from CurseForge API
  2. Version ID Resolution: Fetches game versions and resolves your specified versions to CurseForge IDs:
    • Minecraft versions (with version normalization)
    • Mod loaders (forge, fabric, etc.)
    • Java versions
    • Environments (client/server)
  3. Metadata Preparation: Constructs the upload metadata including:
    • Changelog and display name
    • Release type
    • All resolved game version IDs
    • Project relations (dependencies)
  4. File Upload: Uploads the primary file with metadata to CurseForge
CurseForge’s version resolution is complex. MCReleaser handles matching your version strings to CurseForge’s internal version IDs by querying the appropriate version types.
CurseForge only supports uploading a single file per version. MCReleaser will use the primary file from your bundle.

Complete Example

java \
  -Dname="AwesomeMod" \
  -Dversion="1.5.0" \
  -Ddescription="## Changes\n\n- Added new features\n- Fixed bugs" \
  -DcurseforgeToken="your_token_here" \
  -DcurseforgeProject="123456" \
  -DcurseforgeType="minecraft" \
  -DcurseforgeReleaseType="release" \
  -DcurseforgeGameVersions="1.20.1 1.20.2 1.20.4" \
  -DcurseforgeModLoaders="forge fabric" \
  -DcurseforgeJavaVersion="17" \
  -DcurseforgeEnvironment="client server" \
  -jar mcreleaser.jar

Advanced: With Dependencies

Here’s a complete example with dependencies:
Docker
docker run \
  -v $(pwd)/build/libs:/app/artifacts \
  -e NAME="ConfigurableMod" \
  -e VERSION="2.0.0" \
  -e DESCRIPTION="Major rewrite with new config system" \
  -e CURSEFORGE_TOKEN="$CURSEFORGE_TOKEN" \
  -e CURSEFORGE_PROJECT="654321" \
  -e CURSEFORGE_GAME_VERSIONS="1.20.4" \
  -e CURSEFORGE_MOD_LOADERS="fabric" \
  -e CURSEFORGE_JAVA_VERSION="17" \
  -e CURSEFORGE_ENVIRONMENT="client server" \
  -e CURSEFORGE_RELATIONS='[
    {"slug": "fabric-api", "type": "requiredDependency"},
    {"slug": "cloth-config", "type": "requiredDependency"},
    {"slug": "modmenu", "type": "optionalDependency"},
    {"slug": "optifine", "type": "incompatible"}
  ]' \
  ghcr.io/hsgamer/mcreleaser:master

Hytale Support

For Hytale projects, the configuration is much simpler:
Docker
docker run \
  -v $(pwd)/build/libs:/app/artifacts \
  -e NAME="HytaleMod" \
  -e VERSION="1.0.0" \
  -e DESCRIPTION="My first Hytale mod" \
  -e CURSEFORGE_TOKEN="$CURSEFORGE_TOKEN" \
  -e CURSEFORGE_PROJECT="789012" \
  -e CURSEFORGE_TYPE="hytale" \
  -e CURSEFORGE_RELEASE_TYPE="release" \
  ghcr.io/hsgamer/mcreleaser:master
Hytale projects use a fixed game version ID and don’t require specifying game versions, loaders, or Java versions.

Source Code Reference

The CurseForge platform implementation can be found in:
  • Platform logic: curseforge/src/main/java/me/hsgamer/mcreleaser/curseforge/CurseForgePlatform.java
  • Configuration keys: curseforge/src/main/java/me/hsgamer/mcreleaser/curseforge/CurseForgePropertyKey.java

Key Implementation Features

// Fetch version types and versions from CurseForge
HttpGet versionTypesEndpoint = new HttpGet(endpoint + "/api/game/version-types");
HttpGet versionsEndpoint = new HttpGet(endpoint + "/api/game/versions");

// Resolve version names to IDs
BiConsumer<String, String> addToGameVersions = (versionName, typeSlug) -> {
    Set<Integer> versionTypeIds = versionTypes.asList().stream()
        .filter(versionType -> typeSlug.equalsIgnoreCase(slug))
        .map(versionType -> versionType.get("id").getAsInt())
        .collect(Collectors.toSet());
    // Match and add version IDs
};

// Add different version types
addToGameVersions.accept(gameVersion, "minecraft");
addToGameVersions.accept(modLoader, "modloader");
addToGameVersions.accept(environment, "environment");
addToGameVersions.accept("Java " + javaVersion, "java");

// Prepare metadata
JsonObject metadata = new JsonObject();
metadata.addProperty("changelog", CommonPropertyKey.DESCRIPTION.getValue());
metadata.addProperty("changelogType", "markdown");
metadata.addProperty("displayName", CommonPropertyKey.NAME.getValue());
metadata.addProperty("releaseType", releaseType);
metadata.add("gameVersions", gameVersionsArray);

// Upload with metadata
MultipartEntityBuilder builder = MultipartEntityBuilder.create()
    .addTextBody("metadata", gson.toJson(metadata), ContentType.APPLICATION_JSON)
    .addBinaryBody("file", fileBundle.primaryFile());

API Endpoints

CurseForge uses different endpoints based on the project type:
  • Minecraft: https://minecraft.curseforge.com/api/
  • Hytale: https://legacy.curseforge.com/api/
Both endpoints support:
  • /game/version-types - Get available version types
  • /game/versions - Get available versions
  • /projects/{projectId}/upload-file - Upload a file

Build docs developers (and LLMs) love