Thanks for helping improve CustomSkinLoader. This branch is the Universal generation: one installable Bootstrap jar carries the shared Common runtime, remaps it for the active Minecraft mapping namespace, and applies loader-specific patches at launch time. A successful Java compile is useful, but changes that touch runtime loading, mappings, or transformers also need in-game verification.
- Git.
- A Java 25 JDK. Set
JAVA_HOMEif Java 25 is not the defaultjavaon yourPATH. - The Gradle wrapper from this repository.
- Local Minecraft test instances for the loaders and versions affected by your change.
The build uses Java 25 tooling, while project sources are compiled for Java 8 compatibility unless a module explicitly provides multi-release sources such as Common/src/main/java21.
Use the wrapper instead of a system Gradle installation.
Windows:
.\gradlew.bat clean build --stacktraceLinux/macOS:
./gradlew clean build --stacktraceThe user-facing mod artifact is:
Bootstrap/build/libs/CustomSkinLoader_Universal-<version>.jar
Common/build/libs/Common-<version>.jar is bundled into the Universal jar as META-INF/jar-jar/CustomSkinLoader-Common.jar. Do not publish or ask users to install the Common jar directly.
Common: shared CustomSkinLoader runtime, configuration, skin API loaders, cache, logging, and texture utilities.Common/src/main/java21: Java 21+ multi-release overrides for runtime behavior that benefits from newer JVM APIs.Bootstrap: assembles the installable Universal jar.Bootstrap/Core: runtime installer, remapper, mapping reader, transformer registry, and shared patch logic.Bootstrap/FabricV1: Fabric and Quilt-compatible bootstrap integration.Bootstrap/ForgeV1: legacy Forge coremod bootstrap.Bootstrap/ForgeV2: Forge ModLauncher bootstrap.Bootstrap/NeoForgeV1andBootstrap/NeoForgeV2: NeoForge discovery and transformation bootstrap.Dummy/BootstrapandDummy/Common: compile-time stubs for Minecraft and loader APIs. Keep these minimal; they are not runtime implementations.buildSrc: local Gradle plugin code, including manifest library resolution from launcher metadata..github/workflowsand.github/scripts: CI, release, metadata, and publishing automation.
- Keep changes scoped to the loader, mapping range, API loader, or Common behavior being modified.
- Preserve compatibility across the supported Minecraft and loader matrix unless the change is intentionally narrowing support.
- Prefer small, explicit compatibility branches over broad reflection or version checks when the affected API surface is known.
- Treat
Bootstrap/Core/src/main/resources/customskinloader/mapping.xmland transformer patches as runtime-critical code. Document why a mapping range or target class changed. - Do not edit generated Gradle output under
build/,.gradle/, IDE metadata, or files generated by a local Minecraft test run. - Keep
Dummyclasses limited to the members needed for compilation. Runtime behavior belongs inCommonorBootstrap, not in stubs. - Update
README.md, issue templates, or release metadata when a user-visible feature, supported loader, supported version, or install path changes. - Follow the existing Java style in nearby files. The codebase intentionally avoids adding large abstractions where a focused compatibility patch is clearer.
Before opening a pull request, run the relevant parts of this checklist:
- Run
.\gradlew.bat clean build --stacktraceon Windows, or./gradlew clean build --stacktraceon Linux/macOS. - Install only
Bootstrap/build/libs/CustomSkinLoader_Universal-<version>.jarinto a clean Minecraft instance. - If you changed
Common, confirm the runtime payload is regenerated under.minecraft/CustomSkinLoader/Core/CustomSkinLoader-Common.jar. - If you changed
Bootstrap, mappings, service descriptors, or transformer patches, test at least one Forge or NeoForge instance and one Fabric or Quilt-compatible instance. - If you changed a version range or mapping entry, test the oldest and newest Minecraft versions covered by that range.
- Check
.minecraft/CustomSkinLoader/CustomSkinLoader.logfor loader, remapper, transformer, and skin loading errors. - For skin API, cache, or network changes, test a normal online profile and a cache/local-profile fallback path when possible.
There is currently no standalone test suite that replaces in-game compatibility testing.
Please include:
- A short summary of the behavior change.
- The Minecraft versions and loaders you tested.
- Any relevant
CustomSkinLoader.logsnippets for bootstrap, remapping, or skin loading issues. - Screenshots or reproduction steps for visible texture/rendering fixes.
- Notes about compatibility risk when changing mappings, ASM patches, service descriptors, or build packaging.
Keep pull requests focused. If a cleanup is unrelated to the bug or feature, send it separately so compatibility regressions are easier to review.
Pull requests run the shared GitHub Actions build on windows-latest with PowerShell and Java 25. This is a CI choice; local builds should remain portable across Windows, Linux, and macOS.
Publishing jobs generate the Universal jar plus metadata files from gradle.properties. Beta builds publish moving beta metadata, release builds publish release metadata and upload to distribution platforms. Object-storage upload is optional and is skipped when the required secrets are not configured.
To generate publish metadata locally without uploading, first build the project, then run:
.\.github\scripts\publish-artifacts.ps1 -Channel Beta -LatestJsonName latest-beta.json -DetailJsonName detail-beta.json -SkipObjectStorageBy contributing, you agree that your contribution will be distributed under the repository license. Source code is licensed under GPL-3.0-only; see LICENSE.