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

Minecraft Lua计时器脚本偶发无法向timesave.txt保存数值问题求助

问题根因
  • 核心问题是文件操作逻辑混乱:同时混用Lua默认IO句柄(io.output/io.write)和显式文件句柄,两个句柄操作同个文件时会出现资源冲突,缓存没有正确刷新就关闭,导致偶发写空。
  • 仅在计时启动时执行保存逻辑,暂停计时时没有将最新的停止时间写入文件,程序中途退出时不仅会丢失最新计时,还可能触发半写操作生成空文件。
  • 读取文件时没有做合法性校验:首次运行文件不存在、或文件内容损坏时,读取会返回nil值,运算后写入文件的就是无效值,直接生成空文件。
  • 读取到的字符串内容没有转换为数字类型,偶发会触发隐式类型转换失败,写入异常内容。
修复方案

将文件读写逻辑单独封装,统一使用显式文件句柄操作,增加合法性校验,在计时启动、暂停、恢复三个节点都触发保存。修复后完整代码如下:

name = "Timer"
description = "Just a normal Timer."
positionX = 0
positionY = 0
sizeX = 24
sizeY = 10
scale = 1

START_STOP_KEY = 0x55 --or 'U'
RESET_KEY = 0x4A --or 'J'
--[[
    Timer Module Script by SebyGHG original script by Onix64(Stopwatch)
    按键码可参考Windows虚拟键码表自行修改
]] -------------script-code-------------
timesaved = 0
stopTime = 0
startTime = 0
state = 2

-- 封装保存逻辑
local function saveTime()
    local f, err = io.open("timesave.txt", "w")
    if not f then return end -- 打开失败直接跳过,避免写空
    f:write(startTime, '\n', stopTime)
    f:close()
end

-- 封装读取逻辑
local function loadTime()
    local f, err = io.open("timesave.txt", "r")
    if not f then
        -- 文件不存在则初始化默认值
        startTime = 0
        stopTime = 0
        timesaved = 0
        return
    end
    local resultstart = tonumber(f:read("*line")) or 0
    local resultstop = tonumber(f:read("*line")) or 0
    f:close()
    startTime = resultstop
    stopTime = resultstart
    timesaved = resultstart - resultstop
end

-- 初始化读取
loadTime()

function keyboard(key, isDown)
    if (isDown == true) then
        if (key == RESET_KEY) then
            loadTime()
            state = 0
        elseif (key == START_STOP_KEY) then
            if (state == 0) then
                state = 1
                startTime = os.time() - timesaved
                saveTime() -- 启动时保存
            elseif (state == 1) then
                state = 2
                stopTime = os.time()
                saveTime() -- 暂停时保存
            elseif (state == 2) then
                state = 1
                startTime = startTime + os.time() - stopTime
                saveTime() -- 恢复计时时保存
            end
        end
    end
end

TimerText = "00:00"
TextColor = {r = 30, g = 255, b = 30, a = 255}
function doubleDigit(number)
    if (number < 10) then
        return "0" .. math.floor(number)
    else
        return math.floor(number)
    end
end

function timeText(time)
    local result = ""
    local days = 0
    while (time > 86399) do
        days = days + 1
        time = time - 86400
    end

    local hours = 0
    while (time > 3599) do
        hours = hours + 1
        time = time - 3600
    end

    local minutes = 0
    while (time > 59) do
        minutes = minutes + 1
        time = time - 60
    end

    if (days == 0) then
        if (hours == 0) then
            return doubleDigit(minutes) .. ":" .. doubleDigit(time)
        else
            return math.floor(hours) .. " : " .. doubleDigit(minutes) .. ":" .. doubleDigit(time)
        end
    else
        return math.floor(days) ..
            " : " .. doubleDigit(hours) .. " : " .. doubleDigit(minutes) .. ":" .. doubleDigit(time)
    end
end

function update()
    if (state == 0) then
        TextColor = {r = 255, g = 0, b = 0, a = 255}
        TimerText = "00:00"
    elseif (state == 1) then
        TimerText = timeText(os.time() - startTime)
        TextColor = {r = 0, g = 255, b = 255, a = 255}
    elseif (state == 2) then
        TimerText = timeText(stopTime - startTime)
        TextColor = {r = 255, g = 255, b = 0, a = 255}
    end
end

function render()
    local font = gui.font()
    local tw = font.width(TimerText)

    gfx.color(0, 0, 0, 0)
    gfx.rect(0, 0, tw + 4, 10)

    gfx.color(TextColor.r, TextColor.g, TextColor.b, TextColor.a)
    gfx.text(2, 1, TimerText)
end

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 12:06:05