# Gravestone × Sable Compatibility Patch A minimal patch mod for Minecraft **1.21.1 / NeoForge** that fixes gravestone placement when a player dies on a Sable sub-level (e.g. a **Create Aeronautics** airship). Without this mod, dying mid-flight makes gravestone place its block (and a dirt support block) in the parent world at the player's visible position. The blocks then clip into the airship's collision shape and stall its physics. With this mod installed, the grave is placed inside the airship's plot area, so it lands on the deck and travels with the airship like any other block on it. ## How it works (one paragraph) Sable stores each sub-level's blocks in a far-away "plot" region of the same `Level`. The visible airship position is a logical pose that's applied at render and collision time only. Gravestone's `DeathEvents.playerDeath` calls `GraveUtils.getGraveStoneLocation(level, deathPos)` with the player's world position — but that position is empty space, so the search either fails or places the grave clipping into the airship. This mod uses Mixin Extras' `@WrapOperation` to intercept that single call and substitute the player's position transformed into the sub-level's plot-local frame (`subLevel.logicalPose().transformPositionInverse(playerPos)`). Gravestone's existing search routine then finds the deck above the player's feet and places the grave correctly inside the contraption. If the player isn't on a sub-level when they die, the mod is a no-op. The mod uses **Sable Companion** rather than depending on Sable directly, so it's safe to ship in packs without Sable (the companion's default implementation just returns null for all sub-level queries → graves behave exactly like vanilla gravestone). ## Build Requires **JDK 21**. If you don't already have a Gradle wrapper jar in `gradle/wrapper/`, bootstrap one first (one-time, needs any system Gradle ≥ 8.10 — `sdk install gradle 8.10`, `brew install gradle`, `apt install gradle`, etc.): ```bash gradle wrapper --gradle-version 8.10 ``` Alternatively, copy `gradlew`, `gradlew.bat`, and `gradle/wrapper/` from any recent NeoForge 1.21.1 mod template (e.g. the official [NeoForge MDK](https://github.com/neoforged/MDK)). Then build the mod: ```bash ./gradlew build ``` The output jar is at `build/libs/gravestone_sable_compat-1.0.0.jar`. If Curse Maven is unreachable from your build machine, drop `gravestone-1.21.1-1.0.19.jar` (or any 1.21.1 build) into a `libs/` folder at the project root, comment out the `compileOnly "curse.maven:gravestone-mod-..."` line in `build.gradle`, and uncomment the `compileOnly fileTree(dir: 'libs', ...)` line. To target a newer gravestone build, look up its CurseForge file ID at [curseforge.com/minecraft/mc-mods/gravestone-mod/files](https://www.curseforge.com/minecraft/mc-mods/gravestone-mod/files) (filter to 1.21.1) and update `gravestone_curse_file_id` in `gradle.properties`. The mixin signature has been stable from 1.0.19 through 1.0.37, so any 1.21.1 build should work. ## Runtime requirements Drop the built jar into your modpack alongside: | Mod | Version | |---|---| | NeoForge | 21.1.x (1.21.1) | | [Gravestone (henkelmax)](https://modrinth.com/mod/gravestone-mod) | 1.21.1-1.0.19 or later | | [Sable](https://modrinth.com/mod/sable) | 1.0+ | | [Sable Companion](https://github.com/ryanhcode/sable-companion) | 1.6+ (bundled inside this jar via JarInJar; no separate install needed) | | Create Aeronautics | any version that uses Sable | The mixin only attaches to `de.maxhenkel.gravestone.events.DeathEvents.playerDeath`'s single call to `GraveUtils.getGraveStoneLocation(Level, BlockPos)`. The signature of that call has been stable across gravestone 1.21.1-1.0.19 → 1.0.37, so the mod should work with any of them. If a future build refactors that method, the mixin will fail loudly at load time (`defaultRequire: 1`) rather than silently no-op. ## File layout ``` gravestone-sable-compat/ ├─ build.gradle ├─ gradle.properties ├─ settings.gradle ├─ src/main/java/com/example/gravestonesablecompat/ │ ├─ GravestoneSableCompat.java # tiny @Mod entry point │ └─ mixin/DeathEventsMixin.java # the actual fix (one @WrapOperation) └─ src/main/resources/ ├─ META-INF/neoforge.mods.toml ├─ gravestone_sable_compat.mixins.json └─ pack.mcmeta ``` ## License MIT — go wild.