Skip to content

Reactor fuel rods are never consumed — extractItem result is ignored and capability fallback silently fails #23

Description

@LxyFreely

I found that my reactor work wierd,and here is the issue written by an AI after reading the source code(Actually, I haven't learned how to read Java programs yet.)

Description

The reactor's fuel consumption mechanism in ReactorControllerBlockEntity.tick() has two bugs that together cause uranium and graphite rods to never be consumed from the input slot, allowing the reactor to run indefinitely on a single rod.

Steps to Reproduce

  1. Build a complete reactor multiblock
  2. Place 1 uranium rod and 1 graphite rod in the reactor input slots
  3. Configure a blueprint with any valid rod pattern
  4. Start the reactor
  5. Observe that it runs for far longer than the configured rod lifetime (default 3600 ticks / 3 minutes)

Root Cause

Bug 1 — extractItem return value is never checked

ReactorControllerBlockEntity.java#L222-L226
} else {
ItemStack extractItem1 = capability.extractItem(0, 1, false);
tmpUraniumTimer = uraniumTimer; // Always resets, even if extraction failed
}

The timer is unconditionally reset regardless of whether the extraction actually succeeded. The extracted ItemStack is assigned to a variable but never checked.

Bug 2 — Silent fallback to EmptyItemHandler.INSTANCE

ReactorControllerBlockEntity.java#L212-L214

IItemHandler capability = level.getCapability(
Capabilities.ItemHandler.BLOCK, be.getBlockPos(), Direction.NORTH.getOpposite());
if (capability == null)
capability = EmptyItemHandler.INSTANCE;
If the NeoForge capability lookup fails, the code silently falls back to EmptyItemHandler.INSTANCE, whose extractItem() returns ItemStack.EMPTY without actually removing anything from the inventory. Meanwhile, fuelItem is read directly from be.inventory.getStackInSlot(0), so the slot always appears non-empty.

Additional Finding
Bug 3 — Timer state is not persisted to NBT

ReactorControllerBlockEntity.java#L148-L186

The following fields are never saved to or loaded from NBT: tmpUraniumTimer, tmpGraphiteTimer, uraniumTimer, graphiteTimer, overHeat, overFlowHeatTimer, overFlowLimiter. This means chunk unloading or world reload resets all timers and overheat state back to defaults.

Suggested Fix
Verify the extractItem result before resetting the timer:

Java

ItemStack extracted = capability.extractItem(0, 1, false);
if (!extracted.isEmpty()) {
tmpUraniumTimer = uraniumTimer;
}
Log a warning when falling back to EmptyItemHandler.INSTANCE so the failure is detectable.
Persist timer and overheat state fields in read() / write().
Environment
Mod: Create Nuclear (NeoForge 1.20.1)
Relevant config: CRods.uraniumRodLifetime (default 3600), CRods.graphiteRodLifetime (default 3600)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions