promotional bannermobile promotional banner

Nuclear Craft UPdated

A modern port of NuclearCraft for 1.21 featuring advanced nuclear reactors, realistic fuel processing, and complex radiation mechanics for high-tech gameplay.

File Details

NuclearCraft-1.21.1-1.4.0.jar

  • B
  • May 9, 2026
  • 17.61 MB
  • 65
  • 1.21.1
  • NeoForge

File Name

NuclearCraft-1.21.1-1.4.0.jar

Supported Versions

  • 1.21.1

Curse Maven Snippet

NeoForge

implementation "curse.maven:nuclear-craft-updated-1489663:8061339"
Curse Maven does not yet support mods that have disabled 3rd party sharing

Learn more about Curse Maven

NuclearCraft Fork — Changelog

May 2026


Fission Reactor — Irradiator Rod Slots

  • Added IrradiatorRodSlotBlock and IrradiatorRodSlotBE — a new block that occupies inner reactor core positions alongside fuel cells
  • Rod slots use the existing moderator → fuel cell line geometry to determine local flux; slots in better positions irradiate faster
  • Each slot tracks its own irradiation line count independently (localIrradiationLines) rather than sharing the global reactor total
  • Rod slots registered as valid inner reactor blocks and recognized by the multiblock validation system
  • Wall irradiator and irradiation chamber blocks unchanged — both irradiator types coexist
  • IrradiatorRodSlotBlock.defaultProps() — renamed from properties() to avoid compiler collision with BlockBehaviour.properties() in NeoForge 1.21.1

Irradiated Rod Item

  • New item IrradiatedRodItem — output of all irradiation processes
  • Carries flux_exposure (0–10000), target_isotope, and source_element as per-stack data
  • flux_exposure encodes both reactor geometry quality and fuel radiation value via speedMultiplier() * 100, clamped to 10000
  • Per-stack data uses NCItemStacks (1.21.1 data component API) — getOrCreateTag() / getTag() do not exist in 1.21.1
  • Visual color shifts from dark grey through green, cyan, to blue-white based on exposure value; isFoil() returns true at flux ≥ 6000
  • Not stackable — each rod is an individual processing job
  • Registered in NCItems as IRRADIATED_ROD with ONE_ITEM_PROPERTIES
  • Static helpers: create(), getFluxExposure(), setFluxExposure(), getTargetIsotope(), setTargetIsotope(), getSourceElement(), setSourceElement()

IrradiatorRodSlotBE — Output Pipeline

  • handleRecipeOutput() override — intercepts recipe completion to emit IrradiatedRodItem instead of raw isotope
  • Reads input item and matches against FissionFuel.NC_ISOTOPES to resolve target_isotope and source_element
  • Computes fluxExposure = (int) Math.min(speedMultiplier() * 100, 10000) at completion moment
  • Guard: only overwrites if targetIsotope was successfully resolved

Hot Cell Processor

  • New standalone processor HotCellBE — processes irradiated rods into isotope distributions
  • Registered in Processors.java as HOT_CELL — slot config: 0 fluid in, 1 item in, 0 fluid out, 6 item out
  • First machine in the mod with runtime-computed outputs — quantities calculated from flux_exposure NBT
  • getRecipe() override: reads target_isotope, converts "neptunium/237""neptunium_237", matches recipe by ID suffix
  • HotCellBE.Recipe inner class stores kScale = 2000.0 and ceiling = 0.28

Output probability formula:

P_tier_up(x) = 0.28 × (1 - e^(-x / 2000))
Slot Content Weight
0 Primary tier-up P_tier_up(x)
1 Secondary tier-up P_tier_up(x) × 0.4
2 Same-tier useful 0.15 + (1-P) × 0.10
3 Same-tier useful 0.10 + (1-P) × 0.05
4 Lower-tier byproduct (1-sum 0-3) × 0.5
5 Fragment dust always 1, guaranteed

HotCellRecipes.java

  • ~35 entries covering Th-230 through Es-253
  • Recipe IDs: hot_cell/{isotope_key_underscored}getRecipe() depends on this format exactly
  • Two concerns separated: recipe defines isotope identities (fixed), formula defines counts (flux function)

Config Auto-Update (v1.4.1)

  • Fuel, heat sink, and accelerator cooler configs self-update from JAR on version mismatch
  • Config folders check version.txt on startup; newer bundled version triggers copy before loading
  • Existing user edits on matching version are preserved

Block Color System

New file: client/block/fission/FissionBlockColors.java

  • FUEL_CELL_COLOR — walks nearby positions for FissionControllerBE, reads getCurrentFuel()ItemFuel.group + def.isotopes[0], returns isotope color
  • IRRADIATOR_ROD_SLOT_COLOR — reads own BE input slot, parses registry path "neptunium_237" via split("_(?=\\d)"), returns isotope color
  • HEAT_SINK_COLOR — reads heat/maxHeat from nearest controller, tints white→orange-red as heat rises
  • getIsotopeColor(element, mass) — lookup table mirroring generate_isotope_textures.py exactly (same base_rgb, light_rgb, lerp formula)
  • Registered in ColorHandler.registerBlockColorHandlers()

Fuel Cell & Irradiator Rod Slot — 3D Rod Geometry

  • Both block models redesigned from cube_all to two-element geometry
  • Frame element: full [0,0,0] to [16,16,16] cube, no tint
  • Rod core element: inset [4,0,4] to [12,16,12], tintindex: 0 — receives isotope color
  • rod_core.png: new 16×16 plain white PNG — tint base
  • IrradiatorRodSlotBlock registration now includes noOcclusion() — required to prevent x-ray through adjacent blocks with inset geometry

Casing & Glass Textures

  • casing.png redesigned — 32×32, steel blue-grey family (#4A5054), outer border, inner bevel, corner rivets, horizontal weld seam, vertical division, bolt cluster
  • casing_connected.png — new 32×32 tileable panel, same seam language, no border
  • glass.png — teal tinted, semi-transparent, visible border (unformed state)
  • glass-ctm.png — seamless, nearly clear teal with subtle diagonal shimmer (formed fallback)

Heat Sink Tinted Parent Model

  • heat_sink_tinted.json — new parent model with tintindex: 0 on all faces
  • All 45 heat sink model JSONs updated to use this parent
  • All moved to src/main/resources/ — safe from runData

FissionCasingBlock

  • FORMED BooleanProperty added — set true on multiblock formation, false on deformation; drives glass texture switching via setGlassFormed() in FissionReactorMultiblock
  • VARIANT IntegerProperty(0–21) added for connected texture selection
  • registerDefaultState guarded: if (this.getClass() == FissionCasingBlock.class) — prevents crash when FissionGlassBlock calls super() with a different property set; sets FORMED=false, VARIANT=0 explicitly
  • New fission_reactor_casing.json — plain cube_all using casing.png for the unformed state; previously missing, causing purple/black missing texture on blocks placed outside a multiblock

Connected casing — 44-variant blockstate (generated by gen_blockstates.py):

  • formed=false,*fission_reactor_casing (plain unformed)
  • formed=true,variant=Nfission_reactor_casing_{name}

22 casing variant models (generated by gen_casing_models.py):

  • Panel element [0,0,0] to [16,16,16]: outward faces use #panel without cullface; connected faces use #panel with cullface
  • Border strip elements: 1px slab per outward face, #casing with cullface
  • panel = casing_connected.png; casing = casing.png

casingVariantIndex() — 22 cases mirroring Extreme Reactors:

Outward face count Cases Indices
0 1 (interior) 0
1 1 (face piece) 1
2 12 (edge/frame) 2–13
3 8 (corner) 14–21

Outward face detection uses allBlocks.contains(neighbor.asLong()) — more reliable than instanceof checks; a face is outward iff the neighbor position is not in the multiblock's tracked set.


FissionGlassBlock — Connected Glass System

  • FissionGlassBlock extends FissionCasingBlock
  • 6 BooleanProperty face directions: NORTH, SOUTH, EAST, WEST, UP, DOWN
  • DirectionProperty FACING = BlockStateProperties.FACING — encodes which direction is outward (toward air outside the reactor); set by setGlassFormed() at formation time
  • createBlockStateDefinition adds FORMED + FACING + 6 dirs — does NOT call super (excludes VARIANT)
  • registerDefaultState called in FissionGlassBlock's own constructor; sets FORMED=false, FACING=NORTH, all direction booleans false — prevents stateDefinition.any() from returning an arbitrary formed state
  • connectsTo() matches instanceof FissionGlassBlock only — glass-to-glass edges are seamless; glass-to-casing edges show the border (the gasket between glass and metal must remain visible)
  • updateShape() returns state unchanged when FORMED=true — prevents neighbor change events from overwriting direction booleans set by the formation hook

Glass blockstate — 480 variants:

  • Key order: down, east, facing, formed, north, south, up, west (strictly alphabetical)
  • Unformed: 384 variants (6 facings × 64 direction combos) — all route to plain unformed model
  • Formed: 96 variants (6 facings × 16 perpendicular connection combos)
  • Generated exclusively by gen_glass_bs.py

Glass model architecture — inset pane:

Single inset pane, 1px from block boundary, 1px thick. Only the outward face renders. Border baked into outward face texture per variant — eliminates coplanar translucent geometry that caused ghosting/doubling artifacts against adjacent casing faces.

Pane geometry by facing:

Facing Min Max
north [0,0,1] [16,16,2]
south [0,0,14] [16,16,15]
east [14,0,0] [15,16,16]
west [1,0,0] [2,16,16]
up [0,14,0] [16,15,16]
down [0,1,0] [16,2,16]

Corrected FACE_EDGES UV mapping (verified empirically):

Face Left Right Top Bottom
north east west up down
south west east up down
east south north up down
west north south up down
up west east north south
down west east south north

Multiblock Validation — Glass Corner Exclusion

  • FissionReactorMultiblock now overrides isValidCorner(BlockPos)
  • Returns false if block at position is instanceof FissionGlassBlock
  • Glass is valid on faces only — corners have three outward faces, which breaks the single-outward-face assumption required by the inset pane model

clearStats() — Deformation Fix

  • clearStats() now saves bottomLeft and topRight before any reset
  • setGlassFormed(false) uses the saved bounds to iterate the shell
  • Previously: failed validation with unset bounds caused setGlassFormed to iterate betweenClosed(ZERO, ZERO), deforming nothing; formed glass/casing persisted after the multiblock broke

Asset Safety & Duplicate Detection

  • check_dupes.py — detects and optionally removes duplicate assets between src/main/resources/ and src/generated/resources/
  • Hand-authored assets live in src/main/resources/ — safe from runData overwrite
  • Running runData after hand-authoring without checking for duplicates will cause a Gradle processResources failure

Utility Scripts

Script Purpose
check_dupes.py Detect/fix duplicate assets between source trees
gen_blockstates.py Generate casing blockstate only (glass section removed)
gen_glass_bs.py Generate glass blockstate (480 variants, with facing)
gen_glass_textures.py Generate 96 glass models + outward/seamless textures
gen_casing_models.py Generate 22 casing variant models
generate_isotope_textures.py Generate isotope item textures
gen_glass_models.py Obsolete — models now generated by gen_glass_textures.py; do not run

Correct script order: gen_glass_textures.pygen_glass_bs.pycheck_dupes.py --fix → build


Design Documents Produced

  • NC_Irradiated_Rod_HotCell_Design.md — irradiated rod and hot cell design
  • NC_Transmutation_Pipeline_Design.md — full transmutation pipeline design
  • NC_Multiblock_Texture_Language_Design.md — four-layer texture language (material base → fabrication marks → operational wear → context marks); status: design complete, implementation pending
  • Isotope process map updated to v2.1

Bug Fixes

  • FissionReactorRegistration — added missing IrradiatorRodSlotBE import
  • registerDefaultState crash — calling it unconditionally in a parent constructor causes a crash when a subclass with a different property set calls super(); fixed with class guard in FissionCasingBlock and explicit call in FissionGlassBlock
  • VARIANT in glass blockstate — createBlockStateDefinition calling super added VARIANT to glass, causing all glass blockstate keys to include variant=0 with no matching JSON; fixed by not calling super in glass
  • Blockstate key ordering — vanilla sorts variant keys strictly alphabetically; mismatched order causes all variants to fall back to the default model; all generated blockstates now use alphabetical property order
  • Casing variant always 0 — outward face detection using instanceof FissionCasingBlock missed controller, port, and other shell blocks; replaced with allBlocks.contains()
  • Panel not visible on edge/corner variants — outward faces had cullface set, making them invisible against air; fixed by removing cullface from outward faces
  • Glass UV mapping — single texture applied to all faces used north-face edge mapping for all directions; corrected per-face FACE_EDGES mapping and verified empirically
  • Translucent sorting artifacts — border strip elements in the translucent render pass caused ghosting where coplanar with adjacent casing faces; eliminated by baking border into the outward face texture
  • Unformed glass showing formed model — stateDefinition.any() returned an arbitrary state with FORMED=true; fixed by explicit registerDefaultState in FissionGlassBlock constructor
  • Formed glass persisting after multiblock break — clearStats() reset bounds before setGlassFormed(false) could use them; fixed by saving bounds before reset