-
Notifications
You must be signed in to change notification settings - Fork 435
ComponentAccess
For those that don't like images: the wiki has moved to a new place, http://ocdoc.cil.li/.
This wiki will no longer be updated.
This page describes how to get access to a component's API from Lua. To recap: components are blocks or items that provide some API to Lua programs running on computers connected to said component.
Components all have an address. This address is a UUID, a unique identifier. In most cases it is OK to abbreviate these addresses. For example to get the full address from an abbreviated one you can use component.get
. To get the address of any block in particular, you can use the Analyzer by holding the control key while right clicking the block.
To get a list of all components attached to your computer you can do this:
# lua
Lua 5.2.3 Copyright (C) 1994-2013 Lua.org, PUC-Rio
lua> local component = require("component")
lua> for k,v in component.list() do print(k, v) end
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx keyboard
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx screen
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx gpu
...
Note that item components will usually keep their address even when removed from a computer. So when removing a hard drive and inserting it back in, it will have the same address as before. This is not the case for block components, they will always get a new address after being broken and placed again.
The component API keeps track of one component of each type as a "primary" component. If there are multiple components of the same type, which one will be the primary component is random. You can access the primary component of a specific type via component.xxx
, where xxx
is the type. For example:
lua> =component.gpu.address
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Alternatively you can use component.getPrimary("xxx")
. Just keep in mind that this will throw an error if there is no primary component for the specified type, so you may wish to check that with component.isAvailable("xxx")
first. Having it throw an error is usually clearer than getting a nil dereference later on.
This system is in mainly place to allow the OS to pick the screen to initially output to.
So now that we know how to get the address of components, let's see how we can interact with them. There are two ways to go about this. One is to call component.invoke(address, method, ...)
. For example:
local component = require("component")
component.invoke(modemAddress, "broadcast", port, data)
The usually preferred way will usually be to get a proxy, however. A proxy is simply a table that provides one function for each API callback, named after that callback. In addition, each proxy has two fields: address
, which holds the address of the wrapped component, and type
, which holds the type of the component. You can get a proxy like this:
local component = require("component")
local proxy = component.proxy(address)
-- The call above using the proxy:
proxy.broadcast(port, data)
-- The common proxy fields:
print(proxy.address) -- address passed to component.proxy above
print(proxy.type) -- "modem"
Note that each primary component you access via component.getPrimary
or component.xxx
is in fact a proxy.
Some component callbacks can performed as "direct calls". Direct calls are performed in the computer's worker thread, meaning they will return instantly. Normal calls are delegated to the main server thread, to avoid race conditions and other threading issues, which also means that normal calls will take up to one tick (i.e. 50 ms). Just to be clear: this only applies to component APIs.
An important part of interacting with components are signals. These can be queued by components to notify computers of external changes and events. For example, user input is forwarded to computers via signals. Computers can also queue their own signals, which can be useful for code-reuse, or just notifying other parts of your code asynchronously.