You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

1.19.2 Fabric版ComputerCraft协程无法控制海龟移动问题

问题分析与解决

核心问题

你的代码存在两个关键问题,导致turtle.turnLeft()执行后程序卡住:

  1. 主循环被阻塞:listen()里的rednet.receive()是无超时的阻塞调用,会一直等待消息,协程启动后,主循环无法继续调度协程完成后续操作。
  2. 协程未主动让出控制权:round()函数一次性执行所有海龟操作,没有插入coroutine.yield()让协程暂停并返回主循环,哪怕主循环不阻塞,协程也会一直占用执行权,无法响应新指令。

另外还有个细节问题:downCo和upCo里的local status = 'Done'是局部变量,会覆盖全局的status,导致外部无法获取正确的任务状态。

修复方案

1. 让消息接收非阻塞

给rednet.receive()添加超时参数,比如rednet.receive(0.1),这样主循环会每隔0.1秒检查一次消息,不会一直卡住。

2. 协程主动让出执行权

在round()的每个海龟操作后(或关键节点)加入coroutine.yield(),让协程执行一步就暂停,返回主循环处理消息,下次循环再继续执行剩余步骤。

3. 调整主循环逻辑

主循环需要同时处理消息和推进协程,而不是只有收到消息才恢复协程。

修改后的完整代码

rednet.open('right')
local status = 'None'

io.output(io.stdout)
io.input(io.stdin)

io.write('Control Panel ID: ')
local baseId = tonumber(io.read())
io.write('Blocks: ')
local blcks = tonumber(io.read())

function round()
    turtle.dig()
    coroutine.yield() -- 让出控制权,返回主循环
    turtle.turnLeft()
    coroutine.yield()
    turtle.dig()
    coroutine.yield()
    turtle.forward()
    coroutine.yield()
    turtle.turnRight()
    coroutine.yield()
    turtle.dig()
    coroutine.yield()
    turtle.digDown()
    coroutine.yield()
    turtle.down()
    coroutine.yield()
    turtle.dig()
    coroutine.yield()
    turtle.turnRight()
    coroutine.yield()
    turtle.dig()
    coroutine.yield()
    turtle.forward()
    coroutine.yield()
    turtle.turnLeft()
    coroutine.yield()
    turtle.dig()
    coroutine.yield()
    sleep(0.2)
end

function listen()
    -- 带超时的非阻塞消息接收
    local id, message = rednet.receive(0.1)
    if id and message then
        if message == 'down' then
            print('Down!')
            -- 仅当协程未结束时恢复执行
            if coroutine.status(downCo) ~= 'dead' then
                coroutine.resume(downCo, blcks)
            end
        elseif message == 'up' then
            print('Up!')
            if coroutine.status(upCo) ~= 'dead' then
                coroutine.resume(upCo, blcks)
            end
        elseif message == 'refuel' then
            turtle.refuel()
        elseif message == 'status' then
            rednet.send(baseId, status)
        elseif message == 'stop' then
            print('Stopping!')
            -- 重置协程,支持下次重新启动任务
            downCo = coroutine.create(function(blcks)
                local a = 0
                print('Going down! '..blcks)
                status = 'Going down'
                while a <= blcks do
                    a = a + 1
                    round()
                end
                status = 'Done'
            end)
            upCo = coroutine.create(function(blcks)
                status = 'Going up'
                for i = blcks,1,-1 do
                    turtle.digUp()
                    coroutine.yield()
                    turtle.up()
                    coroutine.yield()
                end
                status = 'Done'
            end)
        elseif message == 'fuel' then
            rednet.send(baseId, turtle.getFuelLevel())
        end
    end
end

downCo = coroutine.create(function(blcks)
    local a = 0
    print('Going down! '..blcks)
    status = 'Going down'
    while a <= blcks do
        a = a + 1
        round()
    end
    status = 'Done' -- 去掉local,修改全局状态变量
end)

upCo = coroutine.create(function(blcks)
    status = 'Going up'
    for i = blcks,1,-1 do
        turtle.digUp()
        coroutine.yield()
        turtle.up()
        coroutine.yield()
    end
    status = 'Done' -- 去掉local
end)

while true do
    listen()
    -- 推进采矿协程(如果处于暂停状态)
    if coroutine.status(downCo) == 'suspended' then
        local success, err = coroutine.resume(downCo)
        if not success then
            print('Down coroutine error: '..err)
        end
    end
    -- 推进上升协程(如果处于暂停状态)
    if coroutine.status(upCo) == 'suspended' then
        local success, err = coroutine.resume(upCo)
        if not success then
            print('Up coroutine error: '..err)
        end
    end
end

额外说明

  • 加入了协程错误捕获:coroutine.resume()返回的第一个值表示执行是否成功,第二个值是错误信息,方便排查问题。
  • stop指令里重置了协程,确保下次可以重新启动采矿任务。
  • 每个海龟操作后都加入了coroutine.yield(),既保证主循环能及时处理新指令,也让协程可以逐步完成采矿流程。

内容的提问来源于stack exchange,提问作者MDdiamond

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 16:10:42