Files
gravestone-sable-compat/README.md

106 lines
4.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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/net/hallada/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.