Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/hbmmods/hbm-s-nuclear-tech-git/llms.txt

Use this file to discover all available pages before exploring further.

NTM’s fluid infrastructure went through a major redesign that produced the MK2 fluid network, built on the same UNINOS node framework that powers the energy system. Unlike Forge’s built-in FluidStack/FluidRegistry model, NTM fluids are identified by FluidType objects registered in com.hbm.inventory.fluid.Fluids — a catalogue of over one hundred fluid types ranging from ordinary water and steam to exotic substances like deuterium, balefire, and various plasma states. Tile entities connect to the network by implementing IFluidConnectorMK2 and calling tryProvide or trySubscribe each tick; pipe blocks implement IFluidPipeMK2 to create and own the nodes that link those tiles together. The legacy interfaces (IFluidStandardReceiver, IFluidStandardSender, IFluidStandardTransceiver) remain functional but are deprecated and delegate directly to their MK2 equivalents.

MK2 vs. Legacy Fluid System

FeatureMK2 (api.hbm.fluidmk2)Legacy (api.hbm.fluid)
StatusCurrent@Deprecated
Network driverFluidNetMK2 via UNINOSSame (delegates to MK2)
Pressure supportYes (int pressure, 0–5)No
Fluid identityFluidTypeFluidType
Convenience baseIFluidStandardReceiverMK2 / IFluidStandardSenderMK2IFluidStandardReceiver / IFluidStandardSender
All three legacy interfaces now extend their MK2 counterparts. You will not lose functionality by keeping legacy code, but the MK2 variants give you pressure-tier support and clearer intent.

MK2 Interface Reference

IFluidUserMK2 — Base Constants

Both IFluidProviderMK2 and IFluidReceiverMK2 extend IFluidUserMK2, which supplies shared constants and the tank accessor:
package api.hbm.fluidmk2;

import api.hbm.tile.ILoadedTile;

public interface IFluidUserMK2 extends IFluidConnectorMK2, ILoadedTile {

    /** Maximum pressure tier index (inclusive). Pressure values run 0 – 5. */
    public static final int HIGHEST_VALID_PRESSURE = 5;

    /** Convenience constant: pressure range covering only tier 0. */
    public static final int[] DEFAULT_PRESSURE_RANGE = new int[] {0, 0};

    /** Returns all tanks belonging to this tile (used by the network for bookkeeping). */
    public FluidTank[] getAllTanks();
}

IFluidConnectorMK2 — Sided Connectivity

package api.hbm.fluidmk2;

import com.hbm.inventory.fluid.FluidType;
import net.minecraftforge.common.util.ForgeDirection;

public interface IFluidConnectorMK2 {

    /**
     * Whether the given side of this tile accepts connections for the given fluid type.
     * dir is the side of THIS block that is being queried.
     * Default: accept all six cardinal sides for any fluid.
     */
    public default boolean canConnect(FluidType type, ForgeDirection dir) {
        return dir != ForgeDirection.UNKNOWN;
    }
}

IFluidConnectorBlockMK2 — Block-Level Connectivity

Implement this on the Block class (not the tile entity) when connectivity must be evaluated from block-access data (e.g. oriented valves):
package api.hbm.fluidmk2;

import com.hbm.inventory.fluid.FluidType;
import net.minecraft.world.IBlockAccess;
import net.minecraftforge.common.util.ForgeDirection;

public interface IFluidConnectorBlockMK2 {

    /**
     * dir is the face going outwards from the block — the direction of the connection.
     */
    public boolean canConnect(FluidType type, IBlockAccess world,
                              int x, int y, int z, ForgeDirection dir);
}

IFluidPipeMK2 — Pipe Tile Entity

Pipe tiles implement IFluidPipeMK2 to gain the createNode(FluidType) helper, which registers a six-way FluidNode for the given fluid type into UNINOS:
package api.hbm.fluidmk2;

import com.hbm.inventory.fluid.FluidType;

public interface IFluidPipeMK2 extends IFluidConnectorMK2 {

    /**
     * Creates and returns a FluidNode centred on this tile with six-directional
     * connections. Call this when the pipe tile is placed or a neighbour changes.
     * Each fluid type that this pipe carries needs its own node.
     */
    public default FluidNode createNode(FluidType type) { ... }
}

IFluidProviderMK2 — Fluid Output

package api.hbm.fluidmk2;

import com.hbm.inventory.fluid.FluidType;

public interface IFluidProviderMK2 extends IFluidUserMK2 {

    /** Remove the given amount of fluid from internal storage. */
    public void useUpFluid(FluidType type, int pressure, long amount);

    /** Returns how much fluid is available to the network this tick. */
    public long getFluidAvailable(FluidType type, int pressure);

    /** Maximum fluid that can leave per tick. Default: effectively unlimited. */
    public default long getProviderSpeed(FluidType type, int pressure) {
        return 1_000_000_000;
    }

    /** Pressure tiers this provider can serve. Default: tier 0 only. */
    public default int[] getProvidingPressureRange(FluidType type) {
        return DEFAULT_PRESSURE_RANGE;
    }
}

IFluidReceiverMK2 — Fluid Input

package api.hbm.fluidmk2;

import com.hbm.inventory.fluid.FluidType;
import api.hbm.energymk2.IEnergyReceiverMK2.ConnectionPriority;

public interface IFluidReceiverMK2 extends IFluidUserMK2 {

    /** Accept fluid. Returns the remainder that could not be stored. */
    public long transferFluid(FluidType type, int pressure, long amount);

    /** How much of this fluid/pressure the tile still needs this tick. */
    public long getDemand(FluidType type, int pressure);

    /** Maximum fluid accepted per tick. Default: effectively unlimited. */
    public default long getReceiverSpeed(FluidType type, int pressure) {
        return 1_000_000_000;
    }

    /** Pressure tiers this receiver can accept. Default: tier 0 only. */
    public default int[] getReceivingPressureRange(FluidType type) {
        return DEFAULT_PRESSURE_RANGE;
    }

    /**
     * Subscribe to a FluidNetMK2 via the pipe at (x,y,z) on face dir.
     * Call every tick for each adjacent pipe face.
     */
    public default void trySubscribe(FluidType type, World world,
                                     int x, int y, int z, ForgeDirection dir) { ... }

    /** Priority within the network for this receiver. */
    public default ConnectionPriority getFluidPriority() {
        return ConnectionPriority.NORMAL;
    }
}

FluidNetMK2 — Network Engine

FluidNetMK2 is created and managed internally by UNINOS. Its per-tick update() method:
  1. Collects all registered providers and sums available fluid per pressure tier.
  2. Collects all registered receivers, groups by priority and pressure tier.
  3. Distributes fluid proportionally within each priority group, highest first.
  4. Debits providers proportionally based on their contribution weight.
  5. Handles rounding errors via a bounded retry loop (max 100 iterations).
public class FluidNetMK2 extends NodeNet<IFluidReceiverMK2, IFluidProviderMK2, FluidNode> {

    /** The fluid type this network transports. Set at construction. */
    protected FluidType type;

    /** Total fluid (mB equivalent) transferred since last tracker reset. */
    public long fluidTracker = 0L;
}

FluidNode — Network Node

package api.hbm.fluidmk2;

import com.hbm.uninos.GenNode;
import com.hbm.util.fauxpointtwelve.BlockPos;
import com.hbm.util.fauxpointtwelve.DirPos;

public class FluidNode extends GenNode<FluidNetMK2> {

    public FluidNode(INetworkProvider<FluidNetMK2> provider, BlockPos... positions) {
        super(provider, positions);
    }

    @Override
    public FluidNode setConnections(DirPos... connections) {
        super.setConnections(connections);
        return this;
    }
}

IFillableItem — Fluid-Carrying Items

Items that carry fluids (canisters, drums, buckets) implement IFillableItem:
package api.hbm.fluidmk2;

import com.hbm.inventory.fluid.FluidType;
import net.minecraft.item.ItemStack;

public interface IFillableItem {

    /** True if this stack can accept the given fluid type. */
    public boolean acceptsFluid(FluidType type, ItemStack stack);

    /** Fill the stack with up to `amount` units. Returns the remainder. */
    public int tryFill(FluidType type, int amount, ItemStack stack);

    /** True if this stack can supply the given fluid type to a tile. */
    public boolean providesFluid(FluidType type, ItemStack stack);

    /** Drain up to `amount` units from the stack. Returns the remainder. */
    public int tryEmpty(FluidType type, int amount, ItemStack stack);

    /** Returns the primary fluid type currently held, or null. */
    public FluidType getFirstFluidType(ItemStack stack);

    /** Returns the current fill level for the primary fluid. */
    public int getFill(ItemStack stack);
}

Legacy Interfaces (Deprecated)

The three legacy interfaces in api.hbm.fluid still work and simply extend their MK2 counterparts with convenience helpers. Prefer the MK2 versions for new code.
@Deprecated
public interface IFluidStandardReceiver extends IFluidStandardReceiverMK2 {

    /** Subscribe to all six adjacent pipe positions in one call. */
    public default void subscribeToAllAround(FluidType type, TileEntity tile) { ... }

    /** Unsubscribe from all adjacent pipe positions. */
    public default void unsubscribeToAllAround(FluidType type, TileEntity tile) { ... }
}
@Deprecated
public interface IFluidStandardSender extends IFluidStandardSenderMK2 {

    /** Push fluid from a tank to one face. */
    public default void sendFluid(FluidTank tank, World world,
                                  int x, int y, int z, ForgeDirection dir) { ... }

    /** Push fluid from a tank to all six adjacent tiles in one call. */
    public default void sendFluidToAll(FluidTank tank, TileEntity tile) { ... }
}
@Deprecated
public interface IFluidStandardTransceiver
        extends IFluidStandardReceiver, IFluidStandardSender { }
A simple combination marker — no additional methods.

Fluid Registration: com.hbm.inventory.fluid.Fluids

NTM fluids are not Forge Fluid instances — they are FluidType objects registered in the Fluids class. A sample of the available types:
// Gases & coolants
public static FluidType WATER, STEAM, HOTSTEAM, SUPERHOTSTEAM, ULTRAHOTSTEAM;
public static FluidType COOLANT, COOLANT_HOT;
public static FluidType HYDROGEN, OXYGEN, XENON, HELIUM3;

// Nuclear materials (as fluids)
public static FluidType DEUTERIUM, TRITIUM;
public static FluidType UF6, PUF6;          // uranium/plutonium hexafluoride
public static FluidType BALEFIRE;            // fictional high-energy fluid

// Petroleum products
public static FluidType OIL, DIESEL, KEROSENE, GASOLINE, NAPHTHA;
public static FluidType HEAVYOIL, BITUMEN, LPG, GAS, PETROLEUM;

// Plasma types
public static FluidType PLASMA_DT, PLASMA_HD, PLASMA_HT, PLASMA_DH3;
public static FluidType PLASMA_XM, PLASMA_BF;

// Misc
public static FluidType MERCURY, LAVA, PEROXIDE, WATZ, CRYOGEL;
Addon mods can listen for fluid registration via IFluidRegisterListener (see api.hbm.fluidmk2.IFluidRegisterListener), registered through Fluids.additionalListeners. This lets you define your own FluidType objects after NTM has set up its core fluids, ensuring your types receive proper IDs and network providers.

Full Implementation Example: Simple Fluid Tank Tile

package com.example.mymod.tile;

import api.hbm.fluidmk2.IFluidStandardReceiverMK2;
import api.hbm.fluidmk2.IFluidStandardSenderMK2;
import com.hbm.inventory.fluid.FluidType;
import com.hbm.inventory.fluid.Fluids;
import com.hbm.inventory.fluid.tank.FluidTank;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.common.util.ForgeDirection;

/**
 * A simple bidirectional fluid tank that accepts water on all sides
 * and can also output water to adjacent pipes/tiles.
 */
public class TileEntityMyFluidTank extends TileEntity
        implements IFluidStandardReceiverMK2, IFluidStandardSenderMK2 {

    // FluidTank(FluidType type, int maxFill, int pressure)
    private final FluidTank tank = new FluidTank(Fluids.WATER, 16_000, 0);

    // -------------------------------------------------------
    // IFluidUserMK2 — expose all tanks
    // -------------------------------------------------------

    @Override
    public FluidTank[] getAllTanks()       { return new FluidTank[]{ tank }; }

    // -------------------------------------------------------
    // IFluidStandardReceiverMK2 — incoming fluid
    // -------------------------------------------------------

    @Override
    public FluidTank[] getReceivingTanks() { return getAllTanks(); }

    // -------------------------------------------------------
    // IFluidStandardSenderMK2 — outgoing fluid
    // -------------------------------------------------------

    @Override
    public FluidTank[] getSendingTanks()   { return getAllTanks(); }

    // -------------------------------------------------------
    // IFluidConnectorMK2 — restrict to water only
    // -------------------------------------------------------

    @Override
    public boolean canConnect(FluidType type, ForgeDirection dir) {
        return type == Fluids.WATER && dir != ForgeDirection.UNKNOWN;
    }

    // -------------------------------------------------------
    // TileEntity lifecycle
    // -------------------------------------------------------

    @Override
    public void updateEntity() {
        if (worldObj.isRemote) return;

        // Subscribe as a receiver on every adjacent pipe face
        for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) {
            trySubscribe(Fluids.WATER, worldObj,
                    xCoord + dir.offsetX,
                    yCoord + dir.offsetY,
                    zCoord + dir.offsetZ, dir);
        }

        // Also push fluid out (acts as a pass-through / buffer)
        for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) {
            tryProvide(tank, worldObj,
                    xCoord + dir.offsetX,
                    yCoord + dir.offsetY,
                    zCoord + dir.offsetZ, dir);
        }
    }

    // -------------------------------------------------------
    // NBT persistence
    // -------------------------------------------------------

    @Override
    public void writeToNBT(NBTTagCompound tag) {
        super.writeToNBT(tag);
        tag.setInteger("waterFill", tank.getFill());
    }

    @Override
    public void readFromNBT(NBTTagCompound tag) {
        super.readFromNBT(tag);
        tank.setFill(tag.getInteger("waterFill"));
    }
}
IFluidStandardReceiverMK2 and IFluidStandardSenderMK2 together implement all of IFluidProviderMK2 and IFluidReceiverMK2 via default methods, so you only need to provide getReceivingTanks(), getSendingTanks(), and getAllTanks(). Implementing both interfaces on the same tile makes it a full transceiver — the equivalent of the deprecated IFluidStandardTransceiver.

Pressure Tiers

The MK2 fluid network supports six pressure tiers (indices 0–5), controlled by the HIGHEST_VALID_PRESSURE = 5 constant on IFluidUserMK2. The pressure is stored per-tank in FluidTank and is used by the network to match compatible providers with receivers:
  • A provider serving tier 1 will only supply receivers that accept tier 1.
  • A receiver that accepts tiers 0–2 must override getReceivingPressureRange() to return new int[]{ 0, 2 }.
  • IFluidStandardReceiverMK2 and IFluidStandardSenderMK2 derive the pressure range automatically from the tanks you expose via getReceivingTanks() / getSendingTanks().
// Manually declare a pressure range spanning tiers 0 through 3:
@Override
public int[] getReceivingPressureRange(FluidType type) {
    return new int[]{ 0, 3 };
}

Build docs developers (and LLMs) love