Create: Computing AgesBrass Docs
Programming the world

Peripherals

The blocks a computer drives: what counts as a peripheral, names by face and on a Data Cable network, wrap, find and call, and code that survives a block being removed.

A peripheral is a block the computer can talk to: a chest whose items it counts, a Create shaft whose speed it reads, a Rotation Speed Controller whose speed it sets, a Traffic Light it switches, a monitor, a radio... The peripheral library finds them and turns each one into a table of functions, its methods.

This guide explains the ideas: what counts as a peripheral, how they are named, how to reach them, and how to write code that keeps working when the world changes. Each kind of block has its own page with every method in detail (see the overview at the end).

What counts as a peripheral

A block is a peripheral when it touches the computer on one of its six faces, or when it touches its Data Cable network (Minicomputer and newer), and the computer knows how to talk to it:

  • the blocks of the mod: Traffic Light, Inductive Loop Detector, monitors, Radio Modem, Wi-Fi Router;
  • Create's Redstone Link;
  • every Create block that turns (kinetic): shafts, motors, presses, the Rotation Speed Controller...;
  • every block that holds items (inventory): chests, barrels, Item Vaults, Depots, Create machines with slots;
  • every block that holds fluids (tank): Create Fluid Tanks and the like;
  • with Create Aeronautics, its sensors and its hot air burner.

A plain stone block, a lamp or a redstone wire is not a peripheral: those are reached with redstone (see Redstone and Create links). Other computers on the cable are not listed as peripherals: computers talk to each other with net.

Tip

The shaft that powers the computer touches its back (its bottom for the Microcontroller), and a shaft is kinetic. So peripheral.wrap("back").speed() tells a program the speed it is running at.

Names: faces and network names

Every peripheral has a name, a string, used to reach it:

  • A block against the computer is named after the face it touches, relative to the screen: "front", "back", "left", "right", "top", "bottom" (the same names as rs, see Redstone and Create links).
  • A block on the Data Cable network gets a network name: its type, an @, and its coordinates, like "inventory@120,64,-35" or "traffic_light@12,70,8". The coordinates are those shown by F3 when you look at the block. The name never changes as long as the block stays in place.

A block that touches both the computer and its cable has both names.

peripheral.list() returns every name, the faces first, then the network names. With a type, it keeps only the peripherals of that type: peripheral.list("inventory"). peripheral.type(name) gives the type of one of them, or nil when there is nothing to talk to on that face.

Data Cable networks

From the Minicomputer on, a computer has a network port. Data Cables touching it form its network, and every block touching those cables becomes one of its peripherals, as far as the cables go (2048 cables at most). The Tube Computer and the Transistor Mainframe have no port: they only reach the six blocks around them.

A few rules of cable networks:

  • Plain shafts, cogwheels and gearboxes along a cable are not peripherals of the network, so a cable running beside a gear train stays clean. Machines that do something (a press, a motor, a speed controller) are.
  • A side of a cable wrenched with a Create Wrench lets nothing through: use it to keep a chest next to the cable out of the network, or to keep two cables side by side apart.
  • Parts of the network in unloaded chunks are simply out of reach until they load again.
  • The network is explored again as soon as a cable is placed or broken. A block placed against an existing cable may take up to a second to appear in peripheral.list().

wrap, find and call

There are three ways to use a peripheral.

**peripheral.wrap(name)** returns a table with the methods of the block, or nil when there is nothing there. Wrap once, at the start, and keep the table:

Brass
local vault = peripheral.wrap("left")        -- an Item Vault on the left
local press = peripheral.wrap("kinetic@40,64,12")
print(vault.count("minecraft:iron_ingot"))
print(press.speed())

**peripheral.find(type)** wraps the first peripheral of a type, the faces first, then the network. No name to type, which is perfect when there is only one of its kind:

Brass
local light = peripheral.find("traffic_light")
if light == nil then
  error("no traffic light found")
end
light.set("green")

**peripheral.call(name, method, ...)** calls one method without keeping a table. Handy for a single call, or with names built by the program:

Brass
peripheral.call("left", "set", "red")
print(peripheral.call("inventory@120,64,-35", "count"))

It stops the program with no peripheral 'left' when nothing answers to that name, and with peripheral 'left' has no method 'sett' for a method the block does not have.

Every wrapped table also has a type() method (any.type()), which returns the type of the block.

A block with several types

A block can be several things at once. A Create Millstone turns and holds items: it is both kinetic and inventory. Its wrapped table has the methods of both, and its type is the first one in this order: Aeronautics sensor, traffic_light, inductive_loop, monitor, radio_modem or wifi_router, redstone_link, kinetic, inventory, tank.

Brass
local mill = peripheral.wrap("left")   -- a Millstone on the left
print(mill.type())                     -- kinetic
print(mill.speed() .. " RPM, " .. mill.count() .. " items inside")

So peripheral.type("left") says "kinetic", but peripheral.list("inventory") and peripheral.find("inventory") include the millstone too: they look at every type of a block, not just the first. On the network, its name starts with its first type: kinetic@x,y,z.

Scanning everything attached

A small program that lists every peripheral with its type and its methods. Save it as scan and run it each time you build something new:

scan
for _, name in ipairs(peripheral.list()) do
  local device = peripheral.wrap(name)
  local methods = table.keys(device)
  table.sort(methods)
  print(name .. " (" .. device.type() .. ")")
  print("  " .. table.concat(methods, " "))
end
Terminal
> scan
back (kinetic)
  capacity overstressed set_speed speed stress type
left (inventory)
  count get list push size type
traffic_light@12,70,8 (traffic_light)
  get release set type

The built-in program devices does the same with a nicer screen.

Robust code: removed and unloaded blocks

A wrapped table does not hold the block itself: each call looks the block up again at its place. So the table never goes stale, but a call can fail when the world has changed:

what happenedwhat a call does
the block was broken or replacedstops the program: not an inventory anymore, not a kinetic block anymore, traffic light removed, monitor removed...
its chunk is not loadedstops the program: peripheral is not loaded
nothing there when wrappingperipheral.wrap and peripheral.find return nil

A program that must run for days protects its calls with pcall, which catches the error and returns a table {ok = true, value = ...} or {ok = false, error = "..."}:

Brass
local vault = peripheral.wrap("left")

local function iron_in_vault()
  if vault == nil then
    vault = peripheral.wrap("left")   -- maybe it was rebuilt
    if vault == nil then
      return nil
    end
  end
  local r = pcall(vault.count, "minecraft:iron_ingot")
  if r.ok then
    return r.value
  end
  vault = nil   -- broken or unloaded: wrap again next time
  return nil
end

while true do
  local iron = iron_in_vault()
  if iron == nil then
    print("vault missing")
  else
    print(iron .. " iron ingots")
  end
  sleep(5)
end

pcall(vault.count, "minecraft:iron_ingot") calls vault.count("minecraft:iron_ingot") and catches its error. When the vault comes back (rebuilt, or its chunk loaded again), the program finds it at the next round without a reboot.

Costs of large networks

Talking to peripherals costs instructions, like everything (see Speed, memory and limits). Most of it is small, but some calls grow with the size of the network:

callinstructions
peripheral.list, peripheral.find16, plus 4 per block touching the cable network
peripheral.wrap8
a network name in wrap, type, call or as the target of push1 per 4 blocks on the network
a method of a wrapped tablea few, plus its own work
inventory list, count, push1 per slot of the inventory
kinetic stress, capacity1 per block of the kinetic network

On a network of 200 blocks, a peripheral.find costs about 800 instructions, nearly three ticks of a Minicomputer at full speed. So wrap once at the start and keep the tables, instead of calling find or call with a network name in a loop. In the same way, a big Item Vault has hundreds of slots: counting it twice a second is nothing for a Personal Computer, but a real load for a slow one.

Overview of the devices

typeblocksmain methodspage
anyevery peripheralany.type()Every device
traffic_lightTraffic Lighttraffic_light.set(), traffic_light.get(), traffic_light.release()Traffic Light
inductive_loopInductive Loop Detectorinductive_loop.detected(), inductive_loop.count()Inductive Loop Detector
monitorCRT Monitor, LCD Monitormonitor.size()Monitors
radio_modem, wifi_routerRadio Modem, Wi-Fi Routerradio.range(), radio.get_ssid(), radio.set_ssid()Radio Modem and Wi-Fi Router
redstone_linkCreate Redstone Linkredstone_link.get(), redstone_link.set(), redstone_link.frequency(), redstone_link.is_receiver()Redstone Link
kineticevery Create block that turnskinetic.speed(), kinetic.stress(), kinetic.capacity(), kinetic.overstressed(), kinetic.set_speed()Create kinetic blocks
inventorychests, barrels, Item Vaults, Depots...inventory.size(), inventory.list(), inventory.get(), inventory.count(), inventory.push()Inventories
tankFluid Tanks and other fluid holderstank.tanks()Tanks
altitude_sensor, gimbal_sensor, velocity_sensor, optical_sensor, navigation_table, swivel_bearing, torsion_springthe sensors and bearings of Create Aeronauticssensor.read() and one method per readingCreate Aeronautics sensors
hot_air_burnerCreate Aeronautics hot air burnerhot_air_burner.amount(), hot_air_burner.set_amount(), hot_air_burner.filled()Hot Air Burner