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)
Maximum FE the storage can hold.
Applied as both maxReceive and maxExtract.
Maximum FE accepted per receiveEnergy call.
Maximum FE dispensed per extractEnergy call.
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
}
}
}