Register custom item radiation values using HazardRegistry, and implement IRadiationImmune or IResistanceProvider to make entities and armor radiation-aware.
Use this file to discover all available pages before exploring further.
NTM’s hazard system is one of the mod’s most distinctive features: every item in a player’s inventory is scanned each tick by HazardSystem, which resolves a list of HazardEntry objects for that item and applies their effects — radiation exposure, heat, chemical toxicity, hydroactive detonation, and more — to the carrier. The system is designed to be extended by addon mods. HazardSystem.register() lets you attach hazard data to any Item, ItemStack, Block, or OreDict key, and HazardModifier subclasses let that data scale dynamically with NBT values (fuel burnup, temperature, etc.). On the entity side, IRadiationImmune grants complete immunity, IResistanceProvider allows partial mitigation per-source, and IRadarDetectableNT makes custom projectiles and vehicles visible on NTM radar screens.
com.hbm.hazard.HazardRegistry is a large static class that registers hazard data for every NTM item. It also exposes a comprehensive set of float constants representing the radiation output (in RADs/s) of real and fictional isotopes, which addon mods can reuse when registering their own items:
// Simplified half-life groups (for RadioactiveCraft compat)public static final float gen_S = 10_000F; // seconds rangepublic static final float gen_H = 2_000F; // hours rangepublic static final float gen_10D = 100F; // ~10 dayspublic static final float gen_100D = 80F;public static final float gen_1Y = 50F;public static final float gen_10Y = 30F;public static final float gen_100Y = 10F;public static final float gen_1K = 7.5F;public static final float gen_10K = 6.25F;public static final float gen_100K = 5F;public static final float gen_1M = 2.5F;public static final float gen_10M = 1.5F;public static final float gen_100M = 1F;public static final float gen_1B = 0.5F;public static final float gen_10B = 0.1F;// Specific isotope constants (RADs/s per item in inventory)public static final float co60 = 30.0F; // Cobalt-60 (5a, β−)public static final float sr90 = 15.0F; // Strontium-90 (29a, β−)public static final float tc99 = 2.75F; // Technetium-99 (211Ka, β−)public static final float i131 = 150.0F; // Iodine-131 (192h, β−)public static final float xe135 = 1250.0F; // Xenon-135 (9h, β−)public static final float cs137 = 20.0F; // Caesium-137 (30a, β−)public static final float au198 = 500.0F; // Gold-198 (64h, β−)public static final float pb209 = 10000.0F; // Lead-209 (3h, β−)public static final float at209 = 7500.0F; // Astatine-209 (5h, β+)public static final float po210 = 75.0F; // Polonium-210 (138d, α)public static final float ra226 = 7.5F; // Radium-226 (1600a, α)public static final float ac227 = 30.0F; // Actinium-227 (22a, β−)public static final float th232 = 0.1F; // Thorium-232 (14Ga, α)public static final float u233 = 5.0F; // Uranium-233 (160Ka, α)public static final float u235 = 1.0F; // Uranium-235 (700Ma, α)public static final float u238 = 0.25F; // Uranium-238 (4.5Ga, α)public static final float np237 = 2.5F; // Neptunium-237 (2.1Ma, α)public static final float pu238 = 10.0F; // Plutonium-238 (88a, α)public static final float pu239 = 5.0F; // Plutonium-239 (24Ka, α)public static final float pu240 = 7.5F; // Plutonium-240 (6600a, α)public static final float pu241 = 25.0F; // Plutonium-241 (14a, β−)public static final float am241 = 8.5F; // Americium-241 (432a, α)public static final float am242 = 9.5F; // Americium-242 (141a, β−)public static final float bf = 300_000F; // Balefire (fictional)
All registration goes through HazardSystem.register(Object key, HazardData data). The key may be an Item, Block, ItemStack, ComparableStack, or an OreDict String.HazardData is a builder that chains addEntry() calls to attach one or more HazardEntry objects (each holding a HazardTypeBase and a base level):
import com.hbm.hazard.HazardData;import com.hbm.hazard.HazardRegistry;import com.hbm.hazard.HazardSystem;// Register a simple radioactive item using HazardRegistry type singletonsHazardSystem.register( MyItems.myUraniumFuel, // the Item to register new HazardData() .addEntry(HazardRegistry.RADIATION, HazardRegistry.u235));// Register by OreDict key — applies to any item in that OreDict groupHazardSystem.register( "ingotUranium235", new HazardData() .addEntry(HazardRegistry.RADIATION, HazardRegistry.u235));// Register a specific ItemStack (item + meta match, no NBT)HazardSystem.register( new ItemStack(MyItems.myHotFuelRod, 1, 0), new HazardData() .addEntry(HazardRegistry.RADIATION, HazardRegistry.pu239) .addEntry(HazardRegistry.HOT, 1.0F));
OreDict registrations are evaluated before item and stack registrations. If the same item matches multiple OreDict keys that have conflicting data, the mutex system (HazardData.setMutex(int bits)) can prevent duplicate application. Bit -1 is reserved internally for the "ingotX" OreDict pattern.
public class HazardData { /** * Add a hazard of the given type at the given base level. * If override = true, all previously fetched entries for this stack * (including OreDict entries) are cleared before this one is added. */ public HazardData addEntry(HazardTypeBase hazard, float level) { ... } public HazardData addEntry(HazardTypeBase hazard, float level, boolean override) { ... } public HazardData addEntry(HazardEntry entry) { ... } /** * Mutex bitmask. If two HazardData objects share a bit, only the first * one (by resolution order) is applied — the second yields. */ public HazardData setMutex(int mutex) { ... }}
public abstract class HazardTypeBase { /** Apply effects to `target` at the computed `level`. */ public abstract void onUpdate(EntityLivingBase target, float level, ItemStack stack); /** Apply effects to a dropped EntityItem (e.g. explode if hydroactive). */ public abstract void updateEntity(EntityItem item, float level); /** Add tooltip lines to the item. Client-side only. */ @SideOnly(Side.CLIENT) public abstract void addHazardInformation(EntityPlayer player, List list, float level, ItemStack stack, List<HazardModifier> modifiers);}
HazardModifier lets you scale a hazard’s base level at runtime, for example based on NBT data (fuel burnup, temperature). Chain modifiers onto a HazardEntry:
import com.hbm.hazard.HazardEntry;import com.hbm.hazard.HazardRegistry;import com.hbm.hazard.modifier.HazardModifier;HazardEntry entry = new HazardEntry(HazardRegistry.RADIATION, HazardRegistry.pu239) .addMod(new HazardModifier() { @Override public float modify(ItemStack stack, EntityLivingBase holder, float level) { // Scale radiation by burnup stored in NBT (0.0 – 1.0) if (stack.hasTagCompound()) { float burnup = stack.getTagCompound().getFloat("burnup"); return level * (1F + burnup * 4F); // up to 5× base at full burnup } return level; } });HazardSystem.register(MyItems.myFuelRod, new HazardData().addEntry(entry));
HazardTransformerBase subclasses are registered in HazardSystem.trafos and called before (transformPre) and after (transformPost) the hazard entry list is assembled from the maps. NTM uses transformers to inject dynamic entries (e.g. ME storage cells containing radioactive items, NBT-tagged radiation containers):
public abstract class HazardTransformerBase { /** Called before the item/oredict maps are queried. Add synthetic entries here. */ public abstract void transformPre(ItemStack stack, List<HazardEntry> entries); /** Called after all map lookups. Filter or modify entries here. */ public abstract void transformPost(ItemStack stack, List<HazardEntry> entries);}
IRadiationImmune is a pure marker interface with no methods. Implement it on any Entity or EntityLivingBase subclass to make that entity completely immune to NTM radiation damage. This is also checked for armor pieces — if worn armor implements IRadiationImmune, the radiation system can treat the wearer as protected.
// Example: a radiation-immune entitypublic class EntityRadiationGolem extends EntityMob implements IRadiationImmune { // no additional methods required}
package api.hbm.entity;import net.minecraft.util.DamageSource;/** * Allows custom entities to specify threshold and resistance values * based on incoming damage type, amount, and piercing values. * Only applies to entities that explicitly implement this interface. */public interface IResistanceProvider { /** * Returns a float[] of {damageThreshold, damageResistance} for this hit. * @param damage The incoming DamageSource * @param amount Raw damage amount * @param pierceDT How much the attack pierces damage threshold * @param pierce How much the attack pierces damage resistance (0–1) */ public float[] getCurrentDTDR(DamageSource damage, float amount, float pierceDT, float pierce); /** Called after damage is resolved — use for reactive behaviour (e.g. cracking armour). */ public void onDamageDealt(DamageSource damage, float amount);}
IResistanceProvider is checked by NTM’s custom damage resolution pipeline for entities that implement it. Standard Minecraft mobs and players are instead governed by DamageResistanceHandler — IResistanceProvider is the more powerful, entity-specific alternative available to addon mod authors.
package api.hbm.entity;public interface IRadarDetectableNT { // Blip level constants (map to RadarEntry.blipLevel) public static final int TIER0 = 0; // micro missiles public static final int TIER1 = 1; // tier-1 missiles public static final int TIER2 = 2; public static final int TIER3 = 3; public static final int TIER4 = 4; // nuclear / thermo / doomsday public static final int TIER10 = 5; // size-10 custom missile public static final int TIER10_15= 6; public static final int TIER15 = 7; public static final int TIER15_20= 8; public static final int TIER20 = 9; public static final int TIER_AB = 10; // anti-ballistic missile public static final int PLAYER = 11; public static final int ARTY = 12; // artillery shell /** Purple blip — use when no other tier applies. */ public static final int SPECIAL = 13; /** Localization key for the radar display name. */ public String getUnlocalizedName(); /** Blip icon / redstone output tier. */ public int getBlipLevel(); /** Whether this entity can be detected by the given radar block. */ public boolean canBeSeenBy(Object radar); /** Whether radar scan parameters (missile/shell/player filters) allow this blip. */ public boolean paramsApplicable(RadarScanParams params); /** Whether this blip contributes to the radar's redstone output. */ public boolean suppliesRedstone(RadarScanParams params); public static class RadarScanParams { public boolean scanMissiles = true; public boolean scanShells = true; public boolean scanPlayers = true; public boolean smartMode = true; public RadarScanParams(boolean m, boolean s, boolean p, boolean smart) { ... } }}
RadarEntry is the object sent from server to client when a radar scan fires. You do not typically construct these yourself; NTM builds them from your entity’s IRadarDetectableNT implementation:
public class RadarEntry { public String unlocalizedName; // display name key public int blipLevel; // IRadarDetectableNT tier constant public int posX, posY, posZ; // block position of the entity public int dim; // dimension ID public int entityID; // for targeting / rendering public boolean redstone; // whether this blip drives redstone output // Convenience constructor from a live entity public RadarEntry(IRadarDetectableNT detectable, Entity entity, boolean redstone) { ... } // ByteBuf serialization (used by NTM's packet system) public void toBytes(ByteBuf buf) { ... } public void fromBytes(ByteBuf buf) { ... }}
api.hbm.recipe.IRecipeRegisterListener is the correct way for addon mods to add recipes to NTM machines. It is called once per SerializableRecipe type during SerializableRecipe.initialize(), after NTM’s defaults are loaded but before the recipe template is written to disk.
package api.hbm.recipe;public interface IRecipeRegisterListener { /** * Called once for every SerializableRecipe class that initialises. * recipeClassName is the simple class name of the recipe type * (e.g. "RecipeMachineBlastFurnace"). Use it to register only the * recipes relevant to that machine. * * Note: SerializableRecipe instances hold only static state — do not * store references to the instances themselves. */ public void onRecipeLoad(String recipeClassName);}
// In your mod's FMLInitializationEvent (or PreInit, before recipes load):import com.hbm.recipes.machines.SerializableRecipe;import api.hbm.recipe.IRecipeRegisterListener;public class MyMod { @Mod.EventHandler public void init(FMLInitializationEvent event) { SerializableRecipe.registerListener(new IRecipeRegisterListener() { @Override public void onRecipeLoad(String recipeClassName) { if ("RecipeMachineBlastFurnace".equals(recipeClassName)) { // Register your blast furnace recipes here } } }); }}
Recipe registration via the older IMCHandler system is deprecated and explicitly noted by NTM’s maintainers as broken on recipe reload. Always use IRecipeRegisterListener for new addon mods.