promotional bannermobile promotional banner

Sable: Destructive

Sable: Destructive makes Sable physics blocks actually break. Real kinetic energy, inertial penetration, density-aware self-damage, radial shockwaves on heavy hits — fast hammers dig deep into dirt, soft hammers shatter against stone, big drops radiate.
Back to Files

Real Sub-Level Mass

File namesabledestructive-1.6.0.jar
Uploaded
Jun 26, 2026
Downloads
29
Size
208.1 KB
Mod Loaders
NeoForge
File ID
8323652
Type
R
Release
Supported game versions
  • 1.21.1

Curse Maven Snippet

NeoForge

implementation "curse.maven:sable-destructive-1524595:8323652"

Learn more about Curse Maven

What's new

The whole break/shockwave pipeline now reads each Sable sub-level's
ACTUAL mass (in kg) from Sable's own `MassData` tracker instead of
treating every attacker as a hard-coded 2000 kg "default ship". Per
the Sable wiki, every block carries a `sable:mass` property (kpg);
`ServerSubLevel#getMassTracker().getMass()` returns the sum that the
physics pipeline itself uses for Rapier. We just read it.

This single change fixes the long-standing complaint that "a tiny
flying chunk feels exactly as heavy as a 5000-block ship": below,
the same 12 m/s impact now produces three very different outcomes
depending on the attacker's real mass.

What is new

- `SubLevelMassResolver` — single source of truth for per-sub-level
mass. O(1) per call (queries `ServerSubLevel#getMassTracker()`),
per-tick identity-keyed cache, defensive fallback to
`defaultAttackerMassKg` on any Sable-side failure. Hard-capped at
`subLevelMassHardCapKg = 1e8 kg` to prevent a corrupted physics
tick from making the energy budget infinite.

- Mass-aware kinetic-energy budget. `BreakResolver.shouldBreakState`
was already a kinetic-energy formula, but it was always fed 2000
kg. Now it sees the real attacker mass, so:
* A 100 kg flying cobblestone at 12 m/s = 7 200 J → bounces off
stone (budget 18 kJ).
* A 50 t small ship at 12 m/s = 3.6 MJ → punches stone wide open.
* A 500 t fortress at 6 m/s = 9 MJ → grinds through obsidian.
The reduced-mass term µ = m1·m2/(m1+m2) means a feather-light
attacker still cannot pulverize a heavy defender — the math
collapses to the attacker's own KE budget.

- Mass-aware structural-toughness gate. The "soft attacker can't
pierce hard defender" rule (`attackerToughnessRatio`) now has a
**mass relief** factor: the required attacker toughness is scaled
by `sqrt(massToughnessReferenceKg / realMass)`, floored at
`massToughnessReliefFloor`. A 100 t crusher made of packed dirt
WILL pulverize stone purely from inertia; a thrown dirt clump
won't. Defaults: `massToughnessReferenceKg = 4000`,
`massToughnessReliefFloor = 0.1` (so at most a 10× relief — a
fully soft Jell-O sub-level can never bypass the gate entirely).

- Shockwave magnitude now uses the same real mass. The bespoke
flood-fill (`computeAttackerMassUnits`, O(N) up to 1500 blocks per
emit) is no longer the primary path — when `useSubLevelMass=true`
we feed Sable's mass tracker × `shockwaveAvgToughnessUnits` (= 120,
i.e. V_STONE × 10) so all existing magnitude thresholds keep their
meaning. Flood-fill remains as the fallback for the unlikely case
where the mass tracker has not been built yet. Net result:
shockwave emission is now O(1) per impact and reflects the real
ship size, not a 6-neighbour sample of it.

- New persistent config knobs (TOML hot-reload as usual):
* `useSubLevelMass`              (bool,  default true)
* `subLevelMassHardCapKg`        (kg,    default 1e8)
* `massToughnessReferenceKg`     (kg,    default 4000)
* `massToughnessReliefFloor`     (×,     default 0.1)
* `shockwaveAvgToughnessUnits`   (units, default 120)

What is fixed

- "Two tiny dirt blocks shouldn't break obsidian by being heavy" —
was actually still happening for SHIP-vs-OBSIDIAN because the
callback was hard-coding 2000 kg. With real mass, a 200 kg dirt
fragment now correctly fails the gate AND fails the energy budget.

- Heavy ships landing softly used to bounce indefinitely because
every contact was rated at 2000 kg @ low speed = 144 kJ, below
every threshold. They now report their real mass, so a 100 t
ship setting down at 4 m/s = 800 kJ punches through dirt/wood as
expected.

- Shockwave was firing inconsistently for big builds because the
flood-fill capped at `shockwaveMassFloodCap = 1500` blocks
underestimated ships larger than that. The real mass tracker has
no such cap.

Backward compatibility

- `useSubLevelMass=false` restores the pre-1.6.0 behaviour exactly
(hardcoded `defaultAttackerMassKg`, flood-fill for shockwave).
- All existing config keys preserved with the same defaults.
- `BreakResolver.shouldBreakState(...)` signature unchanged.
- `ShockwaveEffect.emit(level, center, energy)` overload kept; a
new `emit(level, center, energy, attackerMassKgHint)` overload is
preferred by callers that already have the resolved mass.

Requirements

- Minecraft 1.21.1
- NeoForge 21.1.227+
- Sable 1.1.3+ (uses `ServerSubLevel#getMassTracker()`)

Credits

- Code: Xylos_Official
- Visuals: Viaquelt
- Built on top of Sable by ryanhcode

# MIT License

This mod has no additional files