Skip to content

Repository files navigation

Grounds Resource Pack

library-resource-pack is a Kotlin/JVM library for composing a validated Minecraft resource pack from independently owned contributions. It publishes three modules:

  • resource-pack-api contains the contribution contract and policy types. A feature module such as library-gui should depend only on this module.
  • resource-pack-builder validates contributions, composes a pack, and writes directory or ZIP artifacts. A product/application owns this dependency and the final pack definition.
  • resource-pack-testkit provides assertions for contribution validity, vanilla claims, and deterministic ZIP output in consumer tests.

The supported baseline is Java 25 and Kotlin 2.2.20.

Installation

Artifacts are published to GitHub Packages under gg.grounds:

repositories {
    mavenCentral()
    maven {
        url = uri("https://maven.pkg.github.com/groundsgg/library-resource-pack")
        credentials {
            username = providers.gradleProperty("github.user").orNull ?: System.getenv("GITHUB_ACTOR")
            password = providers.gradleProperty("github.token").orNull ?: System.getenv("GITHUB_TOKEN")
        }
    }
}

dependencies {
    implementation("gg.grounds:resource-pack-api:0.1.0")
    implementation("gg.grounds:resource-pack-builder:0.1.0") // product composer only
    testImplementation("gg.grounds:resource-pack-testkit:0.1.0")
}

Contribute from a library module

Contributing modules return PackContribution; they do not own PackDefinition, ResourcePackComposer, or writer types. This is the intended boundary for library-gui and similar libraries: the imports below are API imports only.

import gg.grounds.resourcepack.api.ContributionId
import gg.grounds.resourcepack.api.PackContribution
import gg.grounds.resourcepack.api.PackEntry
import gg.grounds.resourcepack.api.PackFormatRange
import java.nio.file.Path

fun guiContribution(assets: Path): PackContribution = PackContribution(
    id = ContributionId.of("grounds:gui"),
    supportedFormats = PackFormatRange(65, 65),
    entries = listOf(
        PackEntry.file(
            "assets/grounds/textures/gui/menu.png",
            assets.resolve("textures/gui/menu.png"),
        ),
    ),
)

Compose and inspect in the product

The product composes all contributions and owns the pack-level definition, validation, and output paths. compose validates and throws PackBuildException when the result is invalid; call validate first if the product needs to inspect the full PackValidationResult.

import gg.grounds.resourcepack.api.PackDefinition
import gg.grounds.resourcepack.api.PackFormat
import gg.grounds.resourcepack.builder.DirectoryPackWriter
import gg.grounds.resourcepack.builder.ResourcePackComposer
import gg.grounds.resourcepack.builder.ZipPackWriter
import java.nio.file.Path

fun buildPlatformPack(gui: gg.grounds.resourcepack.api.PackContribution, output: Path) {
    val composer = ResourcePackComposer()
    val definition = PackDefinition(
        description = "Grounds platform",
        format = PackFormat(65),
    )
    val contributions = listOf(gui)
    val validation = composer.validate(definition, contributions)
    validation.throwIfInvalid()

    val pack = composer.compose(definition, contributions)
    DirectoryPackWriter().write(pack, output.resolve("inspection"))
    val artifact = ZipPackWriter().write(pack, output.resolve("platform.zip"))

    println("ZIP: ${artifact.path}")
    println("SHA-1: ${artifact.sha1}")
    println("SHA-256: ${artifact.sha256}")
}

DirectoryPackWriter writes a readable inspection directory. ZipPackWriter writes a deterministic ZIP: entry order and ZIP timestamps are stable for identical input. Its PackArtifact reports the resulting path, byte size, SHA-1, and SHA-256. SHA-1 is supplied for legacy ecosystem compatibility; use SHA-256 when you need a modern integrity identifier.

Claims and validation rules

There is no JSON merging and no last-writer-wins behavior. Each resource path may have exactly one contribution entry. Paths under assets/minecraft/ are vanilla paths: with VanillaPathPolicy.ALLOW_CLAIMED, every such entry needs an exclusive exact VanillaPathClaim, and every claim must correspond to exactly that contribution's entry. The default policy, FORBID, rejects vanilla paths entirely. Validation also reports duplicate contribution IDs and paths, unsupported pack formats, missing or multiply provided rendering capabilities, reserved root paths, and configured size limits.

Test helpers

Use resource-pack-testkit from consumer tests to prove a contribution is valid, that its vanilla claims match its entries, or that a complete pack produces identical ZIP bytes and hashes regardless of contribution ordering:

import gg.grounds.resourcepack.testkit.assertValidContribution
import gg.grounds.resourcepack.testkit.assertVanillaClaimsMatch

assertValidContribution(gui)
assertVanillaClaimsMatch(gui)

Non-goals

This library does not discover assets, load JSON, merge JSON, resolve resource inheritance, choose product-level pack metadata, or publish packs. It also does not permit path conflicts to be resolved by contribution ordering. The product supplies files and policy, then decides where and how to distribute the finished artifact.

About

Typed, deterministic Minecraft resource-pack composition for Grounds libraries

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages