Document 2 of 2 | AprismPrismate Documentation Set Version: v26.23 | Status: Implemented (official) Author: BlockConnect@StarsailsClover Canonical language: English
This guide is written for the engineering assistant implementing
AprismPrismate. Read 01-architecture-design.md first; this document turns it
into concrete, ordered implementation steps with acceptance criteria.
| Tool | Version | Purpose |
|---|---|---|
| JDK | Java 25 (Temurin) | Modern profile compile runtime (Aprism doc 08 Sec 2) |
| Gradle | 9.x | Build orchestration |
| Architectury Loom | latest | Fabric source set (Modern) |
| NeoGradle or ModDevGradle | latest | NeoForge source set |
| cosign | 2.2+ | artifact signing |
You will need the Aprism repository checked out as a sibling: Prismate consumes
aprism-api, aprism-manifest, and aprism-loader-core either via
includeBuild("../Aprism") (preferred during co-development) or published
mavenLocal() artifacts.
Create these Gradle subprojects:
common/ -> java-library. Depends: Aprism API/manifest/loader-core (relocated
at shading), Minecraft (deobf per loader). Contains:
PrismateBootstrap, AjeDiscovery, AjeExtractor, EmbeddedRuntime,
LifecycleMapper, HostBridge (interface).
fabric/ -> depends: common + Fabric Loader (loom). Contains: FabricEntrypoint,
FabricClassloaderBridge, fabric.mod.json.
neoforge/ -> depends: common + NeoForge. Contains: NeoForgeEntrypoint (@Mod),
NeoForgeClassloaderBridge.
forge/ -> visible refusal stub (DECISION-1 re-confirmed; classic Forge
deferred post-1.0). Refuses to boot with a named error.
Shading rule (critical): relocate com.aprism.loader and com.aprism.manifest
-> com.aprism.prismate.internal; do NOT relocate com.aprism.api.
These are exact; copy, do not paraphrase.
IAprismMod: requiredvoid onInitialize(AprismContext); optional no-op defaultsonPreInitialize,onSetup,onComplete.AprismContext:getMod(),getEventBus(),getRegistry(),getLogger().AprismPhaseorder:PREINIT, INIT, SETUP, COMPLETE, then sideCLIENT/SERVER.- Manifest record fields:
schemaVersion, id, version, displayName, description, environment, entrypoints, mixins, depends, platforms, accessWidener, provides, custom. - Environment IDs Prismate must supply:
minecraft,fabricloader(Fabric build),neoforge(NeoForge build),java, plus the loader-specificforgeid for the Forge stub. Also injectaprism(embedded runtime version): Aprism core now supplies this upstream (OPEN-1 closed, v26.0), but Prismate keeps the self-injection as a fallback for embedded cores that predate the upstream fix. Both paths use the same normalization.
Do these in order; each has a concrete acceptance test.
Set up settings.gradle with the three subprojects and a version catalog. Wire
Aprism modules as a composite build.
Accepts: ./gradlew build compiles empty modules.
In common, call Aprism's AprismManifestParser to parse a sample
aprism.manifest.json from a test .aje.
Accepts: unit test parses a valid manifest and rejects a malformed one.
Scan a temp dir of .aje files; for each, extract <modid>.jar, resources/,
mixins/, lib/ into <workdir>/<modid>/.
Accepts: unit test extracts a synthetic .aje and finds all expected entries.
Implement dependency resolution using Aprism's DependencyResolver with the
environment map (Section 3) and lifecycle dispatch calling IAprismMod phase
methods on a sample mod class loaded from an extracted jar.
Accepts: unit test drives PREINIT->INIT->SETUP->COMPLETE on a sample mod and
records the calls in order.
Implement FabricEntrypoint as a Fabric mod with an early entrypoint; in
onInitialize run discovery -> extraction -> classpath injection -> lifecycle.
Use Fabric's classloader add-jar API (confirm OPEN-4). Add resources/ so the
host loads the mod's assets.
Accepts: launch a Fabric instance with Prismate + a sample .aje; the sample
mod's onInitialize runs and (with a resource) the resource is visible.
Register extracted mixins/*.json with the host loader's Mixin environment so
.aje mods that use Mixin actually patch.
Accepts: a sample .aje with a trivial mixin applies it in Fabric.
Mirror Step 5/6 for NeoForge using @Mod constructor + FML setup events.
Accepts: same sample .aje loads and initializes on NeoForge.
Detect the Aprism agent (system property, see OPEN-3) at bootstrap; if present, log a clear error and skip all Prismate work. Accepts: with agent property set, Prismate logs refusal and does not load mods.
Collect per-pack load failures; at the end, log each failed pack + reason.
Accepts: a deliberately broken .aje produces a named, readable failure without
stopping other mods.
Add cosign keyless signing + checksums + GitHub Pre-Release workflow, mirroring the Aprism and AprismRefract pipelines. Bump Prismate version on the same minor line as the embedded Aprism core. Accepts: a signed, checksummed Pre-Release publishes per-loader artifacts.
- Unit tests (common): manifest parse, discovery, extraction, dependency resolution, lifecycle dispatch order — all runnable headless.
- Integration tests (per loader): use the project's MDL launcher tooling (see
the Aprism workspace) to create real Fabric/NeoForge instances, install
Prismate + sample
.aje, launch, and assert the mod initialized (via MDLlogs/gamecommands). - Negative tests: malformed manifest, missing dependency, agent-present refusal.
- Loader classloader injection APIs (OPEN-4/OPEN-5) are loader-internal and may
differ across versions; verify against the exact pinned loader version before
committing to the injection path, and keep the
URLClassLoaderfallback (doc 01 Sec 9.3) ready. - Relocating the Aprism runtime without relocating
com.aprism.apiis the most error-prone build step; add a build-time check thatcom/aprism/apiremains unrelocated in the shaded jar. - Ordering: Aprism mods must be on the classloader before host mods' INIT runs; perform injection in the EARLIEST host entrypoint available.
End of guide.