Sable: Destructive is a NeoForge 1.21.1 add-on for Sable that turns physics blocks into something that can actually be destroyed. Crash a ship into the ground, set off a creeper next to a flying base, or drop an end crystal on a tank — Sable sub-levels now react to violence the way they should: chunks fly off, weak materials pulverize, and reinforced ones hold.
Out of the box, Sable gives you beautifully simulated physics blocks, but they are effectively indestructible. This add-on plugs directly into Sable's collision and explosion callbacks and decides, on every meaningful impact, whether the affected blocks should:
The choice between the two is not a flat dice roll. It is biased by real physics:
You see the underlying numbers right in-game with F3 + H:
Mass: 540 kg
Impact strength: 20 m/s
NaN/Inf, mid-step mutation, and cross-parent cluster errors. Years of "Minecraft just closed without a log" — fixed.config/sabledestructive-common.toml. Every value set via /sable-dv set … survives restarts, and editing the TOML on disk hot-reloads within ~250 ms.0.5 · m · v_thr²). An obsidian hammer punches a deep crater into dirt and only chips the surface of stone, automatically.All commands require op level 2.
/sable-dv on enable the system
/sable-dv off disable the system
/sable-dv toggle flip enabled
/sable-dv status current enabled state
/sable-dv config list list every tunable + current value
/sable-dv config get <name> read one value
/sable-dv config set <name> <value>
/sable-dv config reset <name>
Tunables include chanceDetach, chanceVanish, physicsBiasStrength, minBreakSpeed, absoluteMaxSpeed, detachSafeSpeedCeiling, maxDetachesPerSecond, maxActiveDetachedSubLevels, effects, fancyVanishEffect, affectOnlySubLevelBlocks, and many more.
Designed to stay quiet when nothing is happening, and not to fall over when everything is happening:
levelEvent(2001) if the fancy pipeline is overloaded.Sable: Destructive ships a small, stable, SemVer-covered public API so other mods can teach it about their blocks. Unknown modded blocks otherwise fall back to a deliberately fragile clay-tier default — register an entry and your block participates in real impact / explosion physics with the mass and toughness you choose.
The entire API lives in a single class: com.destroynautics.sabledestructive.api.SableDestructiveAPI. Anything outside that package is internal and may change between versions.
@Mod("examplemod")
public class ExampleMod {
public ExampleMod(IEventBus bus) {
bus.addListener(this::onCommonSetup);
}
private void onCommonSetup(FMLCommonSetupEvent e) {
// Direct Block reference (recommended, type-safe):
SableDestructiveAPI.register(
ExampleBlocks.MITHRIL_BLOCK.get(),
8500.0, // mass in kg
SableDestructiveAPI.Tier.NETHERITE);
// By ResourceLocation (works even if the target Block class isn't loaded —
// useful for optional cross-mod compat):
SableDestructiveAPI.register(
ResourceLocation.fromNamespaceAndPath("othermod", "arcane_brick"),
3000.0,
SableDestructiveAPI.Tier.STONE);
// Custom raw values (advanced):
SableDestructiveAPI.register(
ExampleBlocks.FOAM_PANEL.get(),
40.0, // very light (kg)
0.8); // very fragile (~8 toughness units)
// Bedrock-equivalent:
SableDestructiveAPI.registerUnbreakable(ExampleBlocks.WARDSTONE.get());
}
}
Use SableDestructiveAPI.Tier instead of magic numbers — your blocks then stay balanced relative to vanilla as the mod's defaults evolve.
| Tier | Toughness (units) | Vanilla example |
|---|---|---|
PAPER |
10 | flowers, candles |
LEAF |
15 | leaves, vines |
EARTH |
20 | dirt, sand, gravel |
CLOTH |
30 | wool, hay, cobwebs |
SOFT |
40 | sponge, slime, snow |
CLAY |
60 | clay, ice, terracotta |
WOOD |
120 | logs, planks |
STONE |
200 | stone, cobble |
HARD_STONE |
280 | deepslate |
METAL_SOFT |
340 | gold, copper |
METAL |
420 | iron, anvil |
GEM |
520 | diamond, emerald |
OBSIDIAN |
700 | obsidian |
NETHERITE |
1000 | netherite, ancient debris |
REINFORCED |
2000 | reinforced deepslate |
UNBREAKABLE |
∞ | bedrock, barrier |
// Register / override
SableDestructiveAPI.register(Block, double massKg, double breakSpeedMs)
SableDestructiveAPI.register(Block, double massKg, Tier tier)
SableDestructiveAPI.registerUnbreakable(Block)
// By ResourceLocation (optional cross-mod compat)
SableDestructiveAPI.register(ResourceLocation, double massKg, double breakSpeedMs)
SableDestructiveAPI.register(ResourceLocation, double massKg, Tier tier)
SableDestructiveAPI.registerUnbreakable(ResourceLocation)
// Inspect / remove
boolean SableDestructiveAPI.isRegistered(Block)
void SableDestructiveAPI.unregister(Block)
// Read-only queries (e.g. for your own tooltips / ballistics)
double SableDestructiveAPI.getMassKg(BlockState)
double SableDestructiveAPI.getBreakSpeedMs(BlockState)
double SableDestructiveAPI.getToughnessUnits(BlockState) // m/s × 10
Toughness: N units where N = breakSpeedMs × 10.Add Sable: Destructive as an optional runtime dependency in your neoforge.mods.toml so your mod loads either way:
[[dependencies.examplemod]]
modId = "sabledestructive"
type = "optional"
versionRange = "[1.1.0,)"
ordering = "AFTER"
side = "BOTH"
Then guard your registration call so it doesn't NoClassDefFoundError when Sable: Destructive isn't installed:
if (ModList.get().isLoaded("sabledestructive")) {
ExampleSableCompat.register(); // wraps the SableDestructiveAPI calls
}
MIT.