Skip to main content
General Mechanics uses Forge Energy (FE) — the NeoForge standard energy unit — for all machine power. The API provides three building blocks: CoreEnergyStorage for storing FE, PoweredBlock for exposing storage from a block entity, and EnergizedCrafter for machines that consume energy while crafting.

Energy units

All energy values are expressed in FE (Forge Energy). There is no conversion layer; values passed to the API are raw FE integers.

CoreEnergyStorage

CoreEnergyStorage extends NeoForge’s EnergyStorage. It exposes two additional mutators that EnergyStorage does not provide.
public class CoreEnergyStorage extends EnergyStorage

Constructors

// capacity — max FE stored; maxReceive and maxExtract both equal capacity
public CoreEnergyStorage(int capacity)

// capacity — max FE stored; maxReceive and maxExtract both equal maxTransfer
public CoreEnergyStorage(int capacity, int maxTransfer)

// capacity, maxReceive, maxExtract configured independently; starts at 0 FE
public CoreEnergyStorage(int capacity, int maxReceive, int maxExtract)

// Full control over all four values
public CoreEnergyStorage(int capacity, int maxReceive, int maxExtract, int energy)
capacity
int
required
Maximum FE the storage can hold.
maxTransfer
int
Applied as both maxReceive and maxExtract.
maxReceive
int
Maximum FE accepted per receiveEnergy call.
maxExtract
int
Maximum FE dispensed per extractEnergy call.
energy
int
FE pre-loaded into the storage on construction.

Additional methods

// Overwrite the stored energy value directly (bypasses transfer limits)
public void setStored(int energy)

// Change the maximum capacity at runtime
public void setMaxStorage(int capacity)

PoweredBlock interface

PoweredBlock is a minimal marker interface. Block entities that hold energy must implement it to integrate with the mod’s capability and UI systems.
public interface PoweredBlock {
    CoreEnergyStorage getEnergyStorage();
}
Implement getEnergyStorage() to return the CoreEnergyStorage instance owned by your block entity.

EnergizedCrafter interface

EnergizedCrafter<T extends Recipe<?>> extends the internal Crafter<T> interface. Implement it on block entities that both hold energy and run crafting operations.
public interface EnergizedCrafter<T extends Recipe<?>> extends Crafter<T>

Methods to implement

// Return true if the stored energy meets the required threshold
boolean hasEnoughEnergy(int required)

// FE consumed per tick during a crafting operation
int getEnergyAmount()

Default helpers

// Returns true if the given item can be inserted into the specified slot
default boolean canInsertItem(ItemStackHandler inventory, Item item, int slot)

// Returns true if the given count fits into the destination slot
default boolean canInsertAmount(int count, int fromSlot, int toSlot, CoreItemStackHandler inventory)
The source code notes that canInsertAmount contains a known logic flaw that may produce bugs with certain slot states. Use it with caution and validate edge cases in your implementation.

NeoForge energy capability pattern

Expose CoreEnergyStorage as a NeoForge capability on your block entity so other mods and cables can interact with it:
@Override
public void registerCapabilities(RegisterCapabilitiesEvent event) {
    event.registerBlockEntity(
        Capabilities.EnergyStorage.BLOCK,
        MY_BLOCK_ENTITY_TYPE.get(),
        (blockEntity, side) -> blockEntity.getEnergyStorage()
    );
}

Code example: implementing a powered block

import general.mechanics.api.energy.CoreEnergyStorage;
import general.mechanics.api.energy.PoweredBlock;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;

public class MyMachineBlockEntity extends BlockEntity implements PoweredBlock {

    private final CoreEnergyStorage energyStorage;

    public MyMachineBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
        super(type, pos, state);
        // 100 000 FE capacity, 1 000 FE/t max receive, 0 FE extract
        this.energyStorage = new CoreEnergyStorage(100_000, 1_000, 0);
    }

    @Override
    public CoreEnergyStorage getEnergyStorage() {
        return energyStorage;
    }

    public void tick() {
        int costPerTick = 40; // FE per tick
        if (energyStorage.getEnergyStored() >= costPerTick) {
            energyStorage.setStored(energyStorage.getEnergyStored() - costPerTick);
            // ... perform operation
        }
    }
}

Build docs developers (and LLMs) love