Skip to content

Instantly share code, notes, and snippets.

@dyc3
Last active July 29, 2026 20:38
Show Gist options
  • Select an option

  • Save dyc3/6462f43f84d029809ebadb64d19b9f97 to your computer and use it in GitHub Desktop.

Select an option

Save dyc3/6462f43f84d029809ebadb64d19b9f97 to your computer and use it in GitHub Desktop.
nuclearcraft reactor builder
-- reactor_builder.lua
--
-- Usage:
-- reactor_builder <json file>
-- get json from https://leu-235.com/
--
-- Example:
-- reactor_builder reactor.json
--
-- Starting position:
-- - Turtle is ONE BLOCK ABOVE the bottom-left reactor coordinate.
-- - The block directly below the turtle is reactor coordinate X=1,Y=1,Z=1.
-- - Turtle faces toward increasing X.
-- - Increasing Z is initially to the turtle's right.
--
-- The turtle builds each layer underneath itself.
-- When it runs out of a required block, it pauses and asks you to refill it.
local args = {...}
if #args ~= 1 then
error("Usage: reactor_builder <json file>", 0)
end
local jsonPath = args[1]
local file = fs.open(jsonPath, "r")
if not file then
error("Could not open " .. jsonPath, 0)
end
local reactor = textutils.unserializeJSON(file.readAll())
file.close()
if not reactor then
error("Invalid JSON in " .. jsonPath, 0)
end
local dimensions = reactor.InteriorDimensions
local compressed = reactor.CompressedReactor
if not dimensions or not compressed then
error("JSON is missing InteriorDimensions or CompressedReactor", 0)
end
local WIDTH = dimensions.X
local HEIGHT = dimensions.Y
local DEPTH = dimensions.Z
local MATERIALS = {
FuelCell = {
name = "nuclearcraft:cell_block",
},
Water = {
name = "nuclearcraft:cooler",
metadata = 1,
},
Redstone = {
name = "nuclearcraft:cooler",
metadata = 2,
},
Gold = {
name = "nuclearcraft:cooler",
metadata = 4,
},
Lapis = {
name = "nuclearcraft:cooler",
metadata = 6,
},
Cryotheum = {
name = "nuclearcraft:cooler",
metadata = 10,
},
}
local blocks = {}
local function positionKey(x, y, z)
return x .. "," .. y .. "," .. z
end
for materialName, positions in pairs(compressed) do
local material = MATERIALS[materialName]
if material then
for _, position in ipairs(positions) do
blocks[positionKey(position.X, position.Y, position.Z)] =
materialName
end
else
print("Warning: ignoring unknown material: " .. materialName)
end
end
local function itemMetadata(detail)
return detail.damage or detail.metadata
end
local function itemMatches(detail, material)
if not detail or detail.name ~= material.name then
return false
end
if material.metadata == nil then
return true
end
return itemMetadata(detail) == material.metadata
end
local function findMaterial(materialName)
local material = MATERIALS[materialName]
for slot = 1, 16 do
local detail = turtle.getItemDetail(slot)
if itemMatches(detail, material) then
return slot
end
end
return nil
end
local function selectMaterial(materialName)
while true do
local slot = findMaterial(materialName)
if slot then
turtle.select(slot)
return
end
local material = MATERIALS[materialName]
print()
print("Out of " .. materialName)
print("Required item: " .. material.name)
if material.metadata ~= nil then
print("Required metadata: " .. material.metadata)
end
print("Refill the turtle, then press Enter.")
read()
end
end
local function refuel()
if turtle.getFuelLevel() == "unlimited" then
return
end
while turtle.getFuelLevel() < 1 do
local previousSlot = turtle.getSelectedSlot()
local foundFuel = false
for slot = 1, 16 do
if turtle.getItemCount(slot) > 0 then
turtle.select(slot)
if turtle.refuel(0) then
turtle.refuel(1)
foundFuel = true
break
end
end
end
turtle.select(previousSlot)
if not foundFuel then
print()
print("Out of fuel.")
print("Add fuel to the turtle, then press Enter.")
read()
end
end
end
local function moveForward()
while true do
refuel()
if turtle.forward() then
return
end
if turtle.detect() then
turtle.dig()
else
turtle.attack()
end
sleep(0.1)
end
end
local function moveUp()
while true do
refuel()
if turtle.up() then
return
end
if turtle.detectUp() then
turtle.digUp()
else
turtle.attackUp()
end
sleep(0.1)
end
end
local direction = 0
local currentX = 1
local currentZ = 1
local function turnRight()
turtle.turnRight()
direction = (direction + 1) % 4
end
local function turnLeft()
turtle.turnLeft()
direction = (direction + 3) % 4
end
local function face(targetDirection)
local difference = (targetDirection - direction) % 4
if difference == 1 then
turnRight()
elseif difference == 2 then
turnRight()
turnRight()
elseif difference == 3 then
turnLeft()
end
end
local function stepForward()
moveForward()
if direction == 0 then
currentX = currentX + 1
elseif direction == 1 then
currentZ = currentZ + 1
elseif direction == 2 then
currentX = currentX - 1
elseif direction == 3 then
currentZ = currentZ - 1
end
end
local function moveTo(targetX, targetZ)
if currentX < targetX then
face(0)
while currentX < targetX do
stepForward()
end
elseif currentX > targetX then
face(2)
while currentX > targetX do
stepForward()
end
end
if currentZ < targetZ then
face(1)
while currentZ < targetZ do
stepForward()
end
elseif currentZ > targetZ then
face(3)
while currentZ > targetZ do
stepForward()
end
end
end
local function blockBelowMatches(materialName)
local exists, block = turtle.inspectDown()
if not exists then
return false
end
local material = MATERIALS[materialName]
if block.name ~= material.name then
return false
end
if material.metadata == nil then
return true
end
return block.metadata == material.metadata
or block.damage == material.metadata
end
local function placeBlock(materialName, x, y, z)
if blockBelowMatches(materialName) then
return
end
if turtle.detectDown() then
local _, block = turtle.inspectDown()
error(
string.format(
"Wrong block at X=%d Y=%d Z=%d: %s",
x,
y,
z,
block and block.name or "unknown"
),
0
)
end
selectMaterial(materialName)
while not turtle.placeDown() do
print(
string.format(
"Could not place %s at X=%d Y=%d Z=%d",
materialName,
x,
y,
z
)
)
print("Fix the obstruction or refill the turtle, then press Enter.")
read()
selectMaterial(materialName)
end
end
local function buildLayer(y)
print(string.format("Building layer %d/%d", y, HEIGHT))
for z = 1, DEPTH do
local startX
local endX
local increment
if z % 2 == 1 then
startX = 1
endX = WIDTH
increment = 1
else
startX = WIDTH
endX = 1
increment = -1
end
moveTo(startX, z)
local x = startX
while true do
local materialName = blocks[positionKey(x, y, z)]
if materialName then
placeBlock(materialName, x, y, z)
end
if x == endX then
break
end
face(increment == 1 and 0 or 2)
stepForward()
x = x + increment
end
end
end
print("Reactor dimensions:")
print(string.format(" X: %d", WIDTH))
print(string.format(" Y: %d", HEIGHT))
print(string.format(" Z: %d", DEPTH))
print()
print("Ensure the turtle is:")
print(" 1. One block above reactor coordinate X=1,Y=1,Z=1")
print(" 2. Facing toward increasing X")
print(" 3. Positioned so increasing Z is to its right")
print()
print("Press Enter to begin.")
read()
for y = 1, HEIGHT do
buildLayer(y)
if y < HEIGHT then
moveTo(1, 1)
face(0)
moveUp()
end
end
moveTo(1, 1)
face(0)
print()
print("Reactor interior complete.")
print("Turtle is above X=1,Y=" .. HEIGHT .. ",Z=1")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment