为了能够配合既有代码使用,合理利用服务器资源,所有程序必须遵守本编程规范。
开放式电脑的程序需要:
具体来说,规则如下:
event.pull
系列函数处理事件。只有后台程序才可以使用 event.listen
函数。event.pull
系列函数处理。目的是为了退出程序后键鼠事件不再被处理。建议您在编写 OpenComputer 程序时,直接复制示例中的代码作为开始模板,然后在此基础上实现您的逻辑。
local timer = event.timer(1000, local function() -- 定时器 print("timer!"); end); while true do local id, _, x, y = event.pullMultiple("touch", "interrupted"); -- 中断事件 if id == "interrupted" then print("soft interrupt! exiting..."); event.cancel(timer); -- 清理资源 os.exit(0); -- 退出 -- 点击事件 elseif id == "touch" then print("user touched! x=", arg["x"], "; y=", arg["y"]); end end
local timer = event.timer(1000, local function() -- 定时器 print("timer!"); end); local ifTerminate = false; while true do -- 处理事件 event.pullFiltered(local function (ename, ...) local ename2handling = { -- 点击事件 ["touch"] = local function() print("user touched! x=", arg["x"], "; y=", arg["y"]); end, -- 红石事件 ["redstone_changed"] = local function() print("redstone changed! side=", arg["side"]); end, -- 中断事件 ["interrupted"] = local function() print("soft interrupt! closing..."); -- 这儿不能退出!在 filter 函数之中要返回 true 表示事件被处理了,然后在 pullFiltered 调用之外退出。 ifTerminate = true; -- 标记事件处理结束后退出 end }; if ename2handling[ename] then -- 这个事件是我们想要处理的 ename2handling[ename](); return true; else return false; end end); if ifTerminate then event.cancel(timer); -- 清理资源 os.exit(0); -- 退出 end end
在没有多任务操作系统的情况下编写在后台运行的程序是很麻烦、很原始的。您需要完全手动处理应用程序切入后台、恢复前台的所有逻辑,就如同在 DOS 中一样。在大部分时刻你不需要让多个程序同时在 opencomputers 上执行。因为 opencomputers 的主要目的是为工业控制以及自动化(即通常有一个固定的职责),而不是当作一个个人电脑来使用。
本代码没有经过实际测试,应该无法符合预期运作。本代码的作用仅仅是供您参考和学习操作系统原理,以及给予一个在 OC 中的 bare bones 的多任务的大致实现和思想。
local ifHide = false; -- 程序是否隐藏(后台运行) local outputBuffer = ""; -- 输出缓冲区 local timer = event.timer(1000, local function() -- 定时器 appPrint("timer!"); end); local pullInputThread = nil; -- 一个处理输入事件的 “线程” ——只执行一次的 timer local redstoneEventHandler = event.listen("redstone_changed", local function(addr, side) appPrint("redstone! addr=", addr, "; side=", side); end); -- 监听将程序至于后台 / 前台的键盘事件 local hideShowKeyEventHandler = event.listen("key_up", local function(addr, char) -- 如果按下小键盘0,唤起应用 if char == keyboard.keys.numpad0 then show(); event.push("hide_all_programs"); -- 通知其他程序隐藏自己 -- 如果按下小键盘 1,完全终止应用 elseif char == keyboard.keys.numpad1 then terminate(); end); -- 如果收到 hide_all_programs 信号,隐藏自己。 local hideAllProgramsEventHandler = event.listen("hide_all_programs", local function() hide(); end); -- 将程序至于后台 function hide() ifHide = true; event.cancel(pullInputThread); -- 强制终止正在执行的 pullInput 函数 os.exit(0); -- 直接退出 end -- 恢复程序于前台 function show() ifHide = false; dumpOutBuffer(); -- 将程序的输出 dump 到屏幕上 pullInputThread = event.timer(0, pullInput, 1); -- 执行 pullInput “线程” end -- 完全终止程序 function terminate() event.cancel(timer); -- 注销定时器 event.ignore(redstoneEventHandler); -- 注销红石事件回调 event.ignore(hideShowKeyEventHandler); -- 注销将程序至于后台 / 前台的回调 event.ignore(hideAllProgramsEventHandler); -- 注销 hide_all_programs 信号的回调 end -- 打印 function appPrint(str) outputBuffer += str + "\n"; if not ifHide then print(str); end end -- 在屏幕上显示输出buffer function dumpOutBuffer() print(outputBuffer); end -- 处理键鼠事件 function pullInput() while true do if not ifHide then -- 仅仅在程序不在后台时方处理键鼠事件 local id, _, x, y = event.pullMultiple("touch", "interrupted"); -- 中断事件 if id == "interrupted" then appPrint("soft interrupt! hidding..."); hide(); elseif id == "touch" then appPrint("user touched! x=", arg["x"], "; y=", arg["y"]); end end end end -- main show();