the basic API of the computer is described here, which is available in a global environment
all methods of this API are available to the computer by default
_G / _ENV - link to the global computer environment(not the global environment of the mod, which is available via global in unsafe mode, but the global environment of the script)
sm - link to scrap mechanic api: safe mode | unsafe mode
global - link to global namespace (unsafe mode only)
self - link to ScriptableComputer script (unsafe mode only)
require(libraryName:string):table - gets access to the library with the specified name
isBetterAPI():boolean - returns true if betterAPI is installed and false otherwise
class(parent:class):class - this method allows you to do something like OOP in lua
--class usage
local display = getComponent("display")
display.reset()
display.clear()
-- ball class
local ballClass = class()
function ballClass:init()
self.x = math.random(0, display.getWidth() - 1)
self.y = math.random(0, display.getHeight() - 1)
self.dx = math.random() - 0.5
self.dy = math.random() - 0.5
self.color = sm.color.new(math.random(), math.random(), math.random())
end
function ballClass:tick()
self.x = self.x + self.dx
self.y = self.y + self.dy
if self.x <= 0 or self.x >= display.getWidth() - 1 then self.dx = -self.dx end
if self.y <= 0 or self.y >= display.getHeight() - 1 then self.dy = -self.dy end
end
function ballClass:draw()
display.fillCircle(self.x, self.y, 15, self.color)
end
-- create balls
local balls = {}
for i = 1, 10 do
local ball = ballClass()
ball:init()
table.insert(balls, ball)
end
function callback_loop()
if _endtick then
display.clear()
display.flush()
return
end
display.clear()
for i, ball in ipairs(balls) do
ball:tick()
ball:draw()
end
display.flush()
end
checkArg(argnum, arg, ...) - checks the correctness of the arguments
--checkArg usage
function test(num)
checkArg(1, num, "number", "nil")
if num ~= nil then
return num + 1
end
return true
end
test(1) --ok
test(4) --ok
test(-111) --ok
test(nil) --ok
test("a") --error:
function callback_loop() end
print(...) - displays a message in the chat (make sure that "Allow Chat/Alert/Debug Messages" is enabled in the Permission Tool)
alert(...) - it works exactly the same as print but outputs messages from the top of the screen (make sure that "Allow Chat/Alert/Debug Messages" is enabled in the Permission Tool)
debug(...) - outputs a message to the game's debugging console (works only when developer mode -dev is enabled) (make sure that "Allow Chat/Alert/Debug Messages" is enabled in the Permission Tool)
log(...) - outputs a message to the debugging console in the computer GUI (it always works, does not require to be enabled in the mod settings)
logPrint(...) - outputs a message to the game chat if the mod settings allow it and always outputs this message to the internal debugging console of the computer (even if it is impossible to output a message to the chat)
warning(msg) - outputs a warning to the debugging console in the computer GUI (it always works, does not require to be enabled in the mod settings)
unpack(table):... - decompresses the table into values
tostring(v) - see[www.lua.org/manual/5.1]
tonumber(str) - see[www.lua.org/manual/5.1]
clearregs() - clear all registers
getreg(name: str) -> [number | bool] - get value from register (the value can be written to the register using the composite writer)
setreg(name: str, value: [number | bool]) - set value to register (the value can be read from the register using the composite reader)
type(val) - see[www.lua.org/manual/5.1]
assert(cond: bool, msg: [str | nil]) - see[www.lua.org/manual/5.1]
error(msg, level: [num | nil]) - see[www.lua.org/manual/5.1]
pairs(table) -> (function, value, nil) - see[www.lua.org/manual/5.1]
ipairs(table) -> (function, value, 0) - see[www.lua.org/manual/5.1]
next(table, index) -> (index, value) - see[www.lua.org/manual/5.1]
pcall(f, ...) -> (num, ...) - see[www.lua.org/manual/5.1]
xpcall(f, err) -> (num, result) - see[www.lua.org/manual/5.1]
select(index, ...) -> ... - see[www.lua.org/manual/5.1]
getParentComputers() -> table - returns table of parent computers data
getChildComputers() -> table - returns table of child computers data
getCurrentComputer() -> table - returns table of self computer data
getComponent(name) -> table - returns the api table of the first connected component of the specified type. creates an exception if a component of this type is not connected
getComponents(name) -> table - returns a table with api tables of all connected components of the specified type
getMotorByLabel(label:string) -> table - returns motor by label, if there is no motor with such label, it will return an exception
getMotorsByLabel(label:string) -> table - returns a table of motors with the specified label
getComponentByLabel(componentType:string, label:string) -> table - returns component by label, if there is no component with such label, it will return an exception
getComponentsByLabel(componentType:string, label:string) -> table - returns a table of components with the specified label
clientInvoke(code: str, args...) - performs invokation some code on clients (unsafe mode only)
clientInvokeTo(player_nickname/playerobj, code: str, args...) - performs invokation some code on client (unsafe mode only)
serverInvoke(code: str, args...) - calls the code on the server side from the client. available only from the code executed from clientInvoke (unsafe mode only)
input(color: [smcolor | string | number | nil]) -> bool - input selector (if color specified); returns true if one on selected inputs is true else returns false
ninput(color: [smcolor | string | number | nil]) -> table[num] - if color specified returns table of parent interactable powers; if no color - returns full table of powers
out(value: [num | bool]) - set power and active state of self.interactable
loadstring(code: str, env: table|nil) -> function - make function from code
load(chunk, chunkname, mode, lenv) -> function - make function from code (alternative to loadstring, works identically)
execute(code: str, env: table|nil) - execute string code
getDeltaTime():number - returns the deltatime between game frames
getDeltaTimeTps():number - returns the deltatime between game ticks
reboot() - restarts the computer. however, it does not interrupt the execution of the current block of code. the reboot will happen only after the computer completes the tick code. please note that if the computer often shut down in a short period of time due to a "too long without yielding" error, then you will not be able to restart it programmatically or by giving a logical signal through the "reboot gate" this was done to prevent the creation of lag machines
getMaxAvailableCpuTime():number - returns the maximum time that you can stay in the loop for 1 game tick. however, you cannot use all the processor time every tick, as this will lead to an increase in the lag score counter and as a result, your computer will start skipping ticks and may crash
getSkippedTicks():number - returns the number of ticks that your computer has missed since the previous receipt of control. normally, this method should always return 0, if these values sometimes become greater than 0, you should optimize your code
getLagScore():number - the lag counter. if your computer creates lags, then this value will increase. if this value reaches 10, then your computer will start skipping clock cycles in order to avoid game lags. if this value reaches 100, your computer will crash. if your computer has stopped creating lags, then this value will be deducted at 1 per tick
getUptime():number - returns the computer's running time in game ticks(40 ticks - one second). if the computer skips ticks to using too much processor time, this function will still show the real time of operation. this means that the value can change by more than 1 (if your computer missed a tick)
getTick():number - it works almost the same as getUptime, but it cannot increase by more than 1 in one iteration, even if the computer skips several tick, this variable will never jump by more than one value. thus, if you make a "getUptime() - getTick()", you will get the number of missed tick for the entire time of operation
getDeviceType():string - returns the type of your computer. it can be "computer" or "tablet" (tablets are not available at the moment)
isComponentAvailable(componentTable:table):boolean - checks whether this component is available for circulation (that is, whether it is connected to the computer, and that it has not yet been blown up)
--isComponentAvailable usage
local display = getComponent("display")
function callback_loop()
if not isComponentAvailable(display) then
print("component not available")
return
end
display.clear(sm.color.new(math.random(), math.random(), math.random()))
display.flush()
end
setComponentApi(name:string, api:table) - makes your computer pretend to be components for other computers. call this function without arguments to cancel the API
--setComponentApi usage
--makes a holographic display from a holographic projector (in fact, you'd better use a separate part of the holographic display for this)
local vdisplay = require("vdisplay")
local holo = getComponent("holoprojector")
holo.reset()
holo.clear()
holo.flush()
local width, height = 32, 32
local idBuffer = {}
local callbacks = {
set = function (self, x, y, color)
local index = x + (y * width)
if idBuffer[index] then holo.delVoxel(idBuffer[index]) end
idBuffer[index] = holo.addVoxel(x - (width / 2), (((height - 1) - y) - (height / 2)) + 20, 0, color, 2)
end,
flush = function (self, isForce)
holo.flush()
end
}
setComponentApi("display", vdisplay.create(callbacks, width, height)) --this line will cause your computer to be identified by other computers as a display
function callback_loop()
if _endtick then
holo.reset()
holo.clear()
holo.flush()
return
end
callbacks.update()
--[[ an example of simulated clicks
callbacks.pushClick({0, 0, "pressed", 1})
callbacks.pushClick({0, 0, "released", 1})
]]
--[[ if you know that someone is not looking at your screen now, then it is better to inform the library about it
if mySecretSource_thereIsNoOneAround then
callbacks.updateAudience(0)
else
callbacks.updateAudience(1)
end
]]
end
getComponentApi():name, api - returns what was set using setComponentApi
setLock(state:boolean) - set the flag to true so that the user cannot open the computer UI
getLock():state - returns what was set using setLock
setInvisible(state:boolean) - set the invisibility flag so that your computer cannot be detected using getParentComputers and getChildComputers (you can still transfer data using setComponentApi)
getInvisible():state - returns what was set using setInvisible
--setLock & setInvisible & setComponentApi using
--the invisibility flag makes it so that other computers cannot see this computer using the getParentComputers and getChildComputers methods
--this is necessary in order to protect the computer from direct external interference
--let's say you have blocked the computer's GUI. the computer code can still be read and written using another computer
--to protect against this, there is an invisibility flag
--if you need to protect your code from direct reading/writing to ENV, but you need to communicate with other computers,
--then you can use the network port or use the setComponentApi method so that your computer simulates the behavior
--of the component and your API is accessible via getComponents
--now you will not be able to interact with this computer using getParentComputers and getChildComputers
setInvisible(true)
--now you can't open the gui of the computer
setLock(true)
setComponentApi("tunnel", {
unlock = function()
--my unlock condition
setInvisible(false)
setLock(false)
end
})
--to unlock it, you can now use the following code on another
--this is somewhat similar to unlocking the bootloader on Xiaomi phone
--[[
local tunnel = getComponent("tunnel")
tunnel.unlock()
function callback_loop()
end
]]
--if the invisibility flag is not set, then it would be possible to unlock the computer bypassing your API with your checks
--[[
for _, computer in ipairs(getParentComputers()) do
computer.env.setLock(false)
end
for _, computer in ipairs(getChildComputers()) do
computer.env.setLock(false)
end
]]
function callback_loop()
end
setCode(code:string) - overwrites the computer code but does not restart it.
please note that if you had code encryption enabled, then after using this method, the code will no longer be encrypted. If you need to update the code so that it remains encrypted, you need to call encryptCode() immediately after this method.
getCode():string - returns the current computer code
please note that if the code is encrypted, this method will return a comment for the user, which indicates that the code is encrypted, it will not return the real code or its encrypted form
to avoid UB, before using this method, it is better to insert a check that the code is encrypted using isCodeEncrypted()
setEncryptedCode(bytecode:string, string|nil) - sets the encrypted code, which can be obtained from the enlua library. it can be used to receive OTA updates in encrypted form. the second argument is a comment for the user that can be set for the encrypted code
the changes will take effect after the reboot(you can trigger a software reboot) can be used, for example, to update the code through the antenna.
encryptCode(string|nil):boolean - encrypts the code if it is not encrypted and does nothing if the code is already encrypted.
this action cannot be undone except by overwriting the encrypted code to a new version of the code use setCode() / setEncryptedCode()
this method does not restart the computer.
you can pass a string here as a message for the user who opens the computer with the encrypted code. these message cannot be changed after the code is already encrypted, even if you call this method again.
returns true if the code was encrypted, returns false if it was already encrypted at the time of the call or it could not be encrypted for some reason.
isCodeEncrypted():boolean - returns true if the code was encrypted.
setData(string) - sets the data string of the computer, it is written to the computer block and can be read using getData. the maximum size of this string is 4 kilobytes
getData():string - returns the current string of computer data
setTable(table) - serializes the table and writes it via setData, the total size of the serialized table should not exceed 4 kilobytes
getTable():table - tries to deserialize a string from getData as json. if this is not possible it will return an empty table
setAlwaysOn(state:boolean) - sets the always on flag, after installing it, the computer will work without giving a logical signal
getAlwaysOn():boolean - returns the status of the always on flag
_endtick - this is the value that will be set to true in your _ENV if this is the last iteration of this computer
_enableCallbacks - set this value to true in your _ENV if you want to use alternative callbacks
_disableBsod - if you set this flag to _ENV, the computer will not display an error message on all connected screens and terminals when crashing
onStart() - called when your computer performs the first iteration
onTick(dt:number) - every tick is called. dt in this case is the deltatime of TPS multiplied by the number of skipped ticks by the computer + 1
onStop() - called when your computer does the last iteration
onError(error:string):boolean - called in case of an error during code execution. after performing this function, the computer will crash anyway, return true if you want the computer to reboot after that (in this case you will not receive an error message)
--the code written here is executed only 1 time when the computer is turned on
function onStart()
--the code written here is executed after the code written outside the function
end
function onTick(dt)
--the code written here will be executed every tick when the computer is turned on
--dt in this case is the deltatime of TPS multiplied by the number of skipped ticks by the computer + 1
end
function onStop()
--it is executed when you turn off the computer
end
function onError(err)
--called if an error occurred in your code during execution
--even though you have received an error, it will still cause your computer to crash
--errors in the error handler can only be seen in the game console if you run it with the (-dev) flag
--return true --return true if you want to restart the computer
end
_enableCallbacks = true
callback_loop() - implement this function in your code and it will be an alternative entry point
callback_error(error:string):boolean - called in case of an error during code execution. after performing this function, the computer will crash anyway, if you do not want it, call reboot (in this case you will not receive an error message)
working with callbacks (old style)
--the code written here is executed only 1 time when the computer is turned on
function callback_loop()
if _endtick then
--it is executed when you turn off the computer
return
end
local dt = getDeltaTimeTps() * (getSkippedTicks() + 1)
--the code written here will be executed every tick when the computer is turned on
--dt in this case is the deltatime of TPS multiplied by the number of skipped ticks by the computer + 1
end
function callback_error(err)
--called if an error occurred in your code during execution
--even though you have received an error, it will still cause your computer to crash
--errors in the error handler can only be seen in the game console if you run it with the (-dev) flag
--reboot() --if you want to restart the computer
end
if _endtick then
--it is executed when you turn off the computer
return
end
if not started then
--the code written here is executed only 1 time when the computer is turned on
started = true
return
end
local dt = getDeltaTimeTps() * (getSkippedTicks() + 1)
--the code written here will be executed every tick when the computer is turned on
--dt in this case is the deltatime of TPS multiplied by the number of skipped ticks by the computer + 1