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
相关产品推荐
相关产品推荐

