ComputerCraft is event-driven - whenever your code needs to "wait" for anything, be it a timer or for a sword swing to finish, it "yields" execution and pauses until such time as it's "resumed" with event data.
For example, turtle.attack() works (loosely) along these lines:
function turtle.attack()
local actionID = native.turtle.attack() --# Hidden function we don't have access to in our own scripts,
--# which starts a sword swing and returns without waiting for it to finish.
--# Then loops until an event with the result appears:
repeat
local event, ID, result = os.pullEvent("turtle_event")
until ID == actionID
return result
end
One problem with this is that if a redstone_event occurs while this code is waiting for its turtle_event, it'll pull it from the front of the event queue and then discard it. You won't be able to pull it later in your code, so you'll actually
miss some redstone state changes.
Luckily, the
parallel API offers an easy workaround to this - it allows you to run multiple functions alongside each other as coroutines, passing copies of all events to each of them separately. While one coroutine is yielding the other can be actively executing code (which solves your waiting issues), and if one coroutine doesn't want a certain event, then that won't stop the other from reading its own copy (which solves your redstone issues).
local function swingSword()
while true do
turtle.attack()
end
end
local function doRedstoneStuff()
while true do
local event = os.pullEvent()
if event == "redstone" then --# The quotes are important here!
if rs.getInput(inputPos) then
.
.
.
end
end
end
end
parallel.waitForAny(swingSword, doRedstoneStuff)