Create: Computing AgesBrass Docs
Programming the world

Redstone and Create links

The six faces of the computer, Create Redstone Links and the blocks that answer redstone: read buttons and detectors, drive clutches, gearshifts and whole Create lines.

Redstone is how a computer touches most of the world. A button, a lever, a pressure plate or a Create detector tells the program that something happened; a lamp, a door, a Clutch or a Gearshift does what the program decides. A computer reaches redstone in three ways:

  1. Its six faces, with the rs library: a wire, a button, a lamp or a Create Clutch placed right against it.
  2. Create's Redstone Links, with the link library or a Redstone Link used as a peripheral (Redstone Link): wireless signals, up to 256 blocks away by default.
  3. Devices with their own outputs, driven as peripherals: the Traffic Light, the Inductive Loop Detector, the hot air burner of Create Aeronautics.

The six faces

The faces are named relative to the screen, as you see the computer when you face its screen: front is the screen itself, left and right are your left and your right, top and bottom are above and below.

                    back
             (the shaft is here)
            +-------------------+
            |                   |
     left   |     computer      |   right
            |   (seen from      |
            |      above)       |
            +-------------------+
                    front
                 (the screen)

                     you

Since the names follow the screen, a program keeps working when you build the same setup facing another direction.

Two faces are often taken: the shaft that powers the computer arrives at the back (at the bottom for the Microcontroller, which is driven from below), and a monitor may sit on another face. The other faces are free for redstone.

rs.sides() returns the six names, handy for a loop over every face. Any other name stops the program with bad side 'up' (front, back, left, right, top, bottom).

Reading inputs

rs.get(side) returns the redstone power that the block on that face sends into the computer, from 0 (nothing) to 15 (full power): a lever, a button, a pressure plate, a redstone wire that points at the computer, a powered block, a comparator, a Create Smart Observer, a Redstone Link in receive mode placed against it...

Redstone power is analog: 16 levels, not just on and off. A wire loses one level per block, a comparator reads how full a container is, a Create Analog Lever gives any level you set. To treat a face as a simple switch, test rs.get(side) > 0.

Brass
if rs.get("left") > 0 then
  print("the lever on the left is on")
end
print("power on top: " .. rs.get("top") .. " / 15")

Waiting for a change: the redstone event

Reading a face in a loop works, but wastes instructions. Better: wait for the redstone event. The computer queues one each time an input changes, on any face, including a change of level (7 to 8). The event carries no field: read the faces you care about when it arrives.

Brass
while true do
  os.pull_event("redstone")
  print("left " .. rs.get("left") .. ", right " .. rs.get("right"))
end

Since a button gives an event when it is pressed and when it is released, and a change on another face also gives one, most programs look for an edge: the moment a face goes from off to on (rising edge) or from on to off (falling edge). Remember the last value of each face and compare:

Brass
local last = {}
for _, side in ipairs(rs.sides()) do
  last[side] = rs.get(side)
end

while true do
  os.pull_event("redstone")
  for _, side in ipairs(rs.sides()) do
    local now = rs.get(side)
    if now > 0 and last[side] == 0 then
      print(side .. " turned on")
    elseif now == 0 and last[side] > 0 then
      print(side .. " turned off")
    end
    last[side] = now
  end
end

A program waiting in os.pull_event reads the faces within a tick of the change, so it sees every normal pulse, even the 2-tick pulse of an observer. A program that is busy elsewhere, or sleeps between reads, may look too late and find a short pulse already over: keep such programs in a main loop, or lengthen the pulses with a Create Pulse Extender.

Setting outputs

rs.set(side, power) sends power out of a face: a number from 0 to 15, or true (15) and false (0). Values above 15 count as 15, below 0 as 0. A number with decimals stops the program with bad argument #2 to 'set' (number has no integer representation): round it first with math.floor.

Brass
local level = 11.6                   -- a value computed by the program
rs.set("top", true)                  -- the lamp on top lights up
rs.set("right", 8)                   -- half power, for a comparator line or a Nixie Tube
rs.set("left", math.floor(level))    -- 11
print(rs.get_output("top"))          -- what the computer sends on top: 15

The computer gives strong power, like a redstone block: the lamp or the Clutch touching the face turns on, and a solid block against the face passes the signal on to what touches it.

rs.get_output(side) returns what the computer sends on a face. rs.get(side) is what it receives: the two are different things, and a program can use both on the same face.

Applied at the end of the tick

Changes of outputs are not sent to the world at once: they are applied once, at the end of the tick in which the program ran, with the last value asked. So a loop that switches a face on and off a thousand times in a tick costs the world a single update, and the server never lags.

The other side of it: on and off in the same tick is no pulse at all.

Brass
rs.set("top", true)
rs.set("top", false)   -- same tick: the lamp never sees the 15

rs.set("top", true)
sleep(0.05)            -- one tick: the world sees the 15
rs.set("top", false)   -- a 1-tick pulse

The same rule applies to Redstone Links and to the speed of a Rotation Speed Controller.

Released when the computer stops

what happensthe outputs
the program ends, crashes, or is stopped with Ctrl+Tstay as they are
the computer stops turning (no rotation, overstressed)stay: the computer is frozen
the computer reboots, shuts down, or its chunk unloadsreleased: every face to 0, every Redstone Link silent

So a lamp switched on by a program stays lit after the program ends, until something switches it off or the computer reboots. And a program that starts after a reboot finds every output at 0: set them to a known state at the start.

When an output keeps a machine running, think about the crash. Run the program inside pcall and put things in a safe state whatever happens:

Brass
local function main()
  -- the real program: runs the press line...
end

local result = pcall(main)
rs.set("left", true)   -- the Clutch on the left stops the line, whatever happened
if not result.ok then
  print("line stopped: " .. result.error)
end

Ctrl+T cannot be caught: after it, the outputs stay as they were.

A Redstone Link sends a redstone signal through the air to every link of the same frequency, a pair of items set in its two slots. The computer is a Redstone Link of its own, for as many as 32 frequencies at once, in both directions:

  • link.set(a, b, power) transmits on the frequency made of items a and b (item ids like "minecraft:iron_ingot"; an empty slot is "minecraft:air"). The power is 0 to 15, or true / false, like rs.set.
  • link.get(a, b) returns the strongest power the other links of that frequency transmit within range. The computer never hears its own signal.

Links work within 256 blocks by default (Create's linkRange server setting), in loaded chunks, and carry the full 0 to 15 level. A wrong item id stops the program with unknown item 'minecraft:iron_ingt'; a 33rd frequency with too many link frequencies (max 32).

Once a program has used a frequency (with link.get or link.set), each change of the power received on it queues a link event with the two items and the new power. So, to listen to a frequency, read it once, then wait:

Brass
-- a remote lever: the lamp on top copies the frequency iron + redstone
local A, B = "minecraft:iron_ingot", "minecraft:redstone"
rs.set("top", link.get(A, B))
while true do
  local e = os.pull_event("link")
  if e.a == A and e.b == B then
    rs.set("top", e.power)
  end
end

And to drive a contraption far away, place a Redstone Link in receive mode next to it with the same two items, and transmit:

Brass
link.set("minecraft:iron_ingot", "minecraft:gold_ingot", true)    -- the bridge rises
sleep(10)
link.set("minecraft:iron_ingot", "minecraft:gold_ingot", false)   -- and comes back down

Every Redstone Link signal of the computer stops when it reboots, shuts down or unloads.

Typing item ids is error prone, and changing the frequency means editing the program. Instead, place a Redstone Link against the computer (or on its Data Cable), and put the items in its slots in the world. As a peripheral, it gives the same get and set, on its frequency:

Brass
local radio = peripheral.find("redstone_link")
local f = radio.frequency()
print("frequency: " .. f.a .. " + " .. f.b)
radio.set(15)              -- every receiver of this frequency lights up
print(radio.get())         -- what the other links send on it

It is still the computer that transmits and listens: the block only names the frequency, and swapping the items in its slots retunes the program without touching the code. See Redstone Link for frequency and is_receiver.

Devices with their own outputs

Some blocks of the mod answer redstone by themselves, and give a computer finer control as peripherals:

  • Traffic Light (Traffic Light). Without a computer it follows the strongest redstone input: 0 off, 1 to 4 red, 5 to 7 red and amber, 8 to 11 green, 12 to 14 amber, 15 flashing amber. So rs.set(side, 9) turns a light against the computer green. As a peripheral, set("green") takes control and the light then ignores redstone until release(), even after the program ends or the computer reboots.
  • Inductive Loop Detector (Inductive Loop Detector). It gives 15 while something stands over it (mobs, players, minecarts, boats, Create Aeronautics vehicles), so a loop against the computer triggers redstone events. As a peripheral, count() tells how many.
  • Hot air burner of Create Aeronautics (Hot Air Burner). Its flame follows the redstone it receives: rs.set(side, 15) when it touches the computer, a Redstone Link otherwise.

Driving Create

Many Create blocks change behaviour when powered. A computer that sets their redstone runs the whole contraption:

Create blockwhen powered
Clutchcuts the rotation: everything after it stops
Gearshiftreverses the rotation after it
Sequenced Gearshiftruns its programmed list of moves, then waits for the next signal
Adjustable Chain Gearshiftchanges the speed ratio, from 1 to 2 with the analog level
Nixie Tubeshows the power level, 0 to 15
Redstone Link (transmit mode)sends the signal to its receivers

The Rotation Speed Controller does not listen to redstone: a computer sets its speed as a peripheral, with kinetic.set_speed() (see Create kinetic blocks). The same kinetic peripheral reads the speed and the stress of any Create block.

Brass
local controller = peripheral.wrap("top")   -- a Rotation Speed Controller on top
controller.set_speed(64)                    -- the line now turns at 64 RPM

A press line with a Clutch

A belt of Mechanical Presses makes iron sheets. The motor reaches the line through a Clutch on the left face of the computer; a Smart Observer watching the belt after the last press is wired to the right face. The program presses exactly one batch, then stops the line:

batch
local BATCH = 64
local made = 0
local was_on = rs.get("right") > 0

rs.set("left", false)   -- clutch released: the line runs
while made < BATCH do
  os.pull_event("redstone")
  local on = rs.get("right") > 0
  if on and not was_on then   -- a new sheet in front of the observer
    made = made + 1
  end
  was_on = on
end
rs.set("left", true)    -- clutch powered: the line stops
print(made .. " iron sheets pressed")

The output stays on after the program ends, so the line stays stopped until the next batch.

Reversing with a Gearshift

A drawbridge on a Mechanical Bearing, a lift on a Rope Pulley: the same motor moves them both ways, a Gearshift chooses the direction. With a Gearshift on the right face, one button on the left flips it:

Brass
local up = false
local was_pressed = false
while true do
  os.pull_event("redstone")
  local pressed = rs.get("left") > 0
  if pressed and not was_pressed then
    up = not up
    rs.set("right", up)   -- powered Gearshift: the other direction
  end
  was_pressed = pressed
end

Starting a Sequenced Gearshift

A Sequenced Gearshift runs a list of moves set in its screen ("turn 90°, wait, turn back") each time it receives a signal. The computer decides when: here, each time a train passes the Train Observer wired to the left face (a pressure plate or any detector works the same):

Brass
while true do
  os.pull_event("redstone")
  if rs.get("left") > 0 then
    rs.set("top", true)    -- the Sequenced Gearshift on top starts its sequence
    sleep(0.1)
    rs.set("top", false)   -- ready for the next train
  end
end

Example: a pulse generator

A function that sends a number of pulses, of a chosen length and spacing: to feed a dispenser, start a Sequenced Gearshift several times, or make a lamp blink.

Brass
local function pulse(side, count, length, gap)
  for i = 1, count do
    rs.set(side, true)
    sleep(length)
    rs.set(side, false)
    sleep(gap)
  end
end

pulse("top", 5, 0.1, 0.4)   -- five short pulses, two per second
while true do
  pulse("right", 1, 0.5, 0.5)   -- then a steady 1 Hz clock on the right
end

The shortest pulse is one tick (sleep(0.05)), and lengths are rounded up to whole ticks. On a slow computer the code between two sleeps also takes time: see Speed, memory and limits.

Example: counting items through a funnel

A Smart Observer placed against a funnel gives a pulse each time items go through it. Wired to the left face, it lets the computer count what comes out of a Mechanical Press line, show it on its screen and on a Display Board (through a Display Link pointed at the computer):

counter
local count = 0
local was_on = rs.get("left") > 0

local function show()
  term.clear()
  term.set_cursor(1, 1)
  print("Iron sheets: " .. count)
  display.set({"Iron sheets", tostring(count)})
end

show()
while true do
  os.pull_event("redstone")
  local on = rs.get("left") > 0
  if on and not was_on then
    count = count + 1
    show()
  end
  was_on = on
end

A funnel may move several items at once: then each pulse is one transfer, not one item. To count items exactly, read the target inventory as a peripheral instead (inventory.count()).

Example: a binary-coded output

One face can carry 16 levels, but a redstone wire loses one level per block, and some contraptions only understand on and off. Four faces used as four bits carry a number from 0 to 15 with plain on/off signals: to light one of 16 lamps through a decoder, or to pick one of 16 destinations with four Redstone Links.

Brass
local BITS = {"left", "right", "top", "bottom"}   -- worth 1, 2, 4 and 8

local function show_binary(n)
  local lit = {}
  for i, side in ipairs(BITS) do
    local on = (n // 2 ^ (i - 1)) % 2 == 1
    rs.set(side, on)
    if on then
      table.insert(lit, side)
    end
  end
  return lit
end

print(table.concat(show_binary(11), " "))
print(table.concat(show_binary(4), " "))
Screen
left right bottom
top

11 is 8 + 2 + 1: the faces worth 8, 2 and 1 are on. (n // 2 ^ (i - 1)) % 2 is the bit number i of n. All four faces change in the same tick, since the outputs are applied together at the end of the tick: whatever reads them never sees a half-written number.