CC: Tweaked

CC: Tweaked

42M Downloads

doing sleep breaks a coroutine

12354fdw opened this issue ยท 7 comments

commented

Minecraft Version

1.20.1

Version

1.96.0

Details

When I try to make a script like this

local i = 1
coroutine.wrap(function()
while true do
print(i)
i = i+1
sleep(1)
end
end)()

the coroutine is stopped at the first iteration

commented

so i need another coroutine just to resume it?

commented

so if i call sleep()

os.pullevent("timer") should trigger and then i can resume it?

EDIT:
if not, how could i make it resume the coroutine?

commented

that's working as expected, you need to resume the coroutine after sleep. Since sleep internally invokes coroutine.yield to fetch timer from java LuaVM


If you'd like to use some kind of js like API, you can try coroutinex

commented

Coroutines are commonly an xy problem, what are you trying to do with this coroutine, there's probably an easier way to do it (commonly the parallel API).

Mentioning the parallel API, it can be a good reference implementation for how to use coroutines.

If you really do have to use the coroutine API then you need to capture the wrapped coroutine and resume it with coroutine.resume. I would use this guide for more information: https://web.archive.org/web/20230213155922/http://www.computercraft.info/forums2/index.php?/topic/25670-bbs-guide-to-coroutines/

commented

so i need another coroutine just to resume it?

In Lua, there is nothing really executing parallel, and Lua do not have the event cycle you have in JS. Therefore, you have to control how they executes manually.
coroutine.wrap is not magic. It just a wraps coroutine.resume to the function it returns. You still have to continuously invoking the function it returns to resume the coroutine.

A basic example is:

local thread = coroutine.create(function()
    local i = 0
    while true do
        print(i)
        i = i+1
        sleep(1)
    end
end)
local res = table.pack(coroutine.resume(thread))
while coroutine.status(thread) ~= 'dead' do
    res = table.pack(coroutine.resume(thread, coroutine.yield(table.unpack(res, 2, res.n))))
end

Or if you prefer coroutine.wrap:

local resumeFn = coroutine.wrap(function()
    local i = 0
    while true do
        print(i)
        i = i+1
        sleep(1)
    end
end)
local res = table.pack(resumeFn())
while true do -- resumeFn will throw "cannot resume dead coroutine" when invoking, you may have to catch that
    res = table.pack(resumeFn(coroutine.yield(table.unpack(res, 1, res.n))))
end
commented

If you really do have to use the coroutine API then you need to capture the wrapped coroutine and resume it with coroutine.resume. I would use this guide for more information: https://web.archive.org/web/20230213155922/http://www.computercraft.info/forums2/index.php?/topic/25670-bbs-guide-to-coroutines/

Btw some information in the post is outdated. In CC: T, coroutine is not creating Java thread anymore, so it's safe to create thousand coroutines as long as you won't use all the space of the os queue

commented

thanks for recommending me the parallel API