Links
Tags
Creators
Details
0.12.0
Compatibility
Changes
v0.12.0 — NeoForge 1.21.1 support + data-integrity hardening
BetterAutoSave now ships from a single source tree as both a Forge 1.20.1 and a NeoForge 1.21.1 build. The async-save core (scheduling, the relay state machine, workers, diagnostics) is zero-Minecraft-dependency pure Java, source-merged and shared by both loaders. This release also fixes the silent loss of chunk capability data (#8) and the data-integrity issues found in a pre-release code review.
NeoForge 1.21.1
- For NeoForge 21.1.x, Java 21+, server-side only; jar:
shinoyuki_betterautosave-neoforge-0.12.0.jar - Features, config, commands, and compatibility modes are identical to the Forge 1.20.1 build
- Serialization and disk-IO glue verified point-by-point against decompiled 1.21.1 sources; all 7 mixin injection points survive; entity region IO moved into SimpleRegionStorage in 1.21.1, adapted through a two-hop accessor so the async entity pipeline is reused as-is
- Async chunk save now includes NeoForge data attachments and the LevelChunk auxiliary light field, matching the vanilla on-disk format — mods using data attachments will not lose data during async saves
- Verified on a real NeoForge 1.21.1 server: all mixins load, periodic and operational
/save-allrun without main-thread stalls, workers drain cleanly on shutdown, restart loads with zero corruption
Data-integrity fixes
- Silent chunk-capability data loss (#8): in the default PARTIAL mode, the main-thread hand-built chunk NBT omitted the
ForgeCapsblock Forge injects at the end ofChunkSerializer.write, so any mod storing data in a chunk capability (e.g. illusion) lost it on every async save and lost it world-wide after a normal restart. PARTIAL/DISABLED now serialize ForgeCaps on the main thread, matching the vanilla format (the NeoForge data-attachment path was already correct) - SavedData async-write race: a mod's
save()may return a live internal tag; while a worker serializes it asynchronously, the mod mutating it can throwConcurrentModificationExceptionor write a torn NBT. The outer tag is now deep-copied before hand-off, matching NeoForge vanillaSavedData.save's own copy - Data loss on degraded fallback: when workers all die from a systemic failure (typically OOM) and the pipeline degrades, queued tasks that had already declared their data "saved" but were never written used to be skipped by the shutdown flush and lost. The degrade transition now drains the residual tasks — chunks restore their unsaved flag for the vanilla synchronous fallback, SavedData is re-marked dirty, and entity losses (no coordinate recovery) are reported — all thread-safe
Other hardening
- The in-flight serializing counter is compensated under extreme queue OOM, so shutdown no longer burns its full timeout and falsely reports unsaved data
- SavedData atomic writes clean up the temp file if any step fails, leaving no orphans
- Operational
/save-all flush's intentional deviations from a few vanilla side-effects are now documented; behavior unchanged
Upgrading
Drop-in jar replacement, no config changes. Forge users on 0.11.x are strongly encouraged to upgrade — 0.11.x still carries the #8 chunk-capability loss risk
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:WAXR3mM5:T2cUFJh4"
}
// Legacy Loom dependency
dependencies {
modImplementation "maven.modrinth:WAXR3mM5:T2cUFJh4"
}

