Links
Tags
Creators
Details
0.3.3
Compatibility
Required content
Changes
Closing the gaps around block state.
A sweep for one shape of bug: an API that quietly does less than it looks like it does. Everything below compiled, ran, and either lost data or had no way to express the thing its own documentation described.
Truncation — a state index is 12 bits, not 4
RetroBlockState.getIndex() puts its low nibble in vanilla metadata and bits 4–11 in the sidecar. Three APIs took a bare 4-bit meta, so a block with more than 16 states silently lost everything above the nibble:
RetroFeatures.setBlock(world, x, y, z, state)— a world feature could not place one.RetroWorldGen.setStateInChunk(...)— a custom chunk generator could not place one at all.RetroMultiblock.Match.fill(world, state)— a multiblock could only be formed out of the low nibble.
If you store block state as an int anywhere, this is the trap: it looks correct up to state 15, then wraps instead of failing.
A tier that can refuse
RetroToolTier.NONE sits below every tier, so it satisfies no needs_<tier>_tool requirement. A Dynamic/Contextual tier previously had no way to say "this tool cannot harvest this block" — null means "no opinion, fall through", and falling through lands on WOOD. A drill bit that only bites certain ores is now .tier((stack, block, player) -> isOre(block) ? DIAMOND : NONE).
Placement that does not notify
RetroStates.set(...) always notified neighbors, which during generation can cascade a block update back into the chunk still being built, with no way to opt out. Added RetroStates.setWithoutNotifyingNeighbors(...) and placeWithoutNotifyingNeighbors(...) (block + state in one call). The position is still marked dirty and a dedicated server still syncs the index — those are not neighbor updates, and skipping them would leave the block invisible rather than merely un-notified.
Textures
RetroTextures.getOrAddItemTexture(...) / getOrAddBlockTexture(...). addItemTexture allocates a new atlas slot on every call, so two callers wanting the same sprite quietly burned a slot and got two handles to one image. The get-or-add form is safe on either side and at any time — which is what code that tints a sprite someone else registered needs. Also RetroToolTier.getTagName(), for building needs_<tier>_tool ids from code.
The test harness had the same disease
The conversion pipeline documented four stages and ran three. Stage 4 — load the reverse-converted world on a plain, non-StationAPI server and prove the modded content is runtime-valid, not merely intact on disk — existed as a written, documented scenario and was wired into no task. Disk verification proves the bytes survived; this proves the world is usable, which is the actual claim. It runs now, and it passes. A failing populate stage also used to sail through silently; it is gated where it is written.
Full feature set: https://matthewperiut.github.io/retroapi/features-0.3.0.html
Built and validated with -Pstationapi on Ornithe (b1.7.3): all four launch smoke suites, plus the now-complete four-stage conversion pipeline (populate → forward/reverse convert → runtime verify).
Projects on Modrinth are automatically available through a Maven repository for use with JVM build tools such as Gradle. To learn more about the Modrinth Maven API, click here.
Note: When available, you should use the creator's maven repo instead as it will have transitive dependency information that the Modrinth Maven API does not. You may also end up with duplicate dependencies if you use a mix of Modrinth and non-Modrinth Maven repositories for your dependencies, because the group identifier will be different when served through the Modrinth Maven API.
Maven coordinates:
Version ID:
build.gradle:
repositories {
exclusiveContent {
forRepository {
maven {
name = "Modrinth"
url = "https://api.modrinth.com/maven"
}
}
// forRepositories(fg.repository) // Uncomment when using ForgeGradle
filter {
includeGroup "maven.modrinth"
}
}
}
// Standard Gradle dependency
dependencies {
implementation "maven.modrinth:iFaqJ8QH:CmBhWlLW"
}
// Legacy Loom dependency
dependencies {
modImplementation "maven.modrinth:iFaqJ8QH:CmBhWlLW"
}


