Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local args = {...}
- -- Configuration --
- local cc_directory = "/usr/cc"
- local cc_lua_directory = cc_directory.."/lua"
- local cc_save_directory = cc_directory.."/data"
- -- OpenOS modules --
- local oc_computer = require("computer")
- local oc_component = require("component")
- local oc_filesystem = require("filesystem")
- local oc_term = require("term")
- local oc_event = require("event")
- local oc_keyboard = require("keyboard")
- local oc_sides = require("sides")
- local oc_bit32 = require("bit32")
- local oc_os = os
- local oc_io = io
- local gpu = oc_component.gpu
- gpu.setResolution(51, 19)
- ---------------------------
- -- ComputerCraft modules --
- ---------------------------
- local eventQueue = {{}}
- local timerList = {}
- local alarmList = {}
- local ccEnv = {_VERSION = _VERSION}
- ccEnv._G = ccEnv
- ccEnv._ENV = setmetatable({}, {__index = ccEnv})
- ccEnv._CC_DISABLE_LUA51_FEATURES = true
- local os = {}
- local fs = {}
- local term = {}
- local parallel = {}
- local colors = {}
- local colours = {}
- local redstone = {}
- local rednet = {}
- local http
- -- FS API --
- function fs.open(path, mode)
- while path:sub(1, 1) == "/" do path = path:sub(2) end
- local handle = {}
- --print(path, mode)
- local realHandle, errorMessage = oc_io.open(cc_save_directory.."/"..path, mode)
- if not realHandle then
- realHandle, errorMessage = oc_io.open(cc_lua_directory.."/"..path, mode)
- end
- if errorMessage then
- --print("Error: "..errorMessage)
- return nil, errorMessage
- end
- function handle.close(...) return realHandle:close(...) end
- if mode == "w" or mode == "a" then
- function handle.write(...) return realHandle:write(...) end
- function handle.writeLine(data) return realHandle:write(data.."\n") end
- function handle.flush(...) return realHandle:flush(...) end
- elseif mode == "r" then
- --function handle.read(...) return realHandle:read(...) end
- function handle.readLine() return realHandle:read() end
- function handle.readAll() return realHandle:read("*a") end
- --function handle.seek(...) return realHandle:seek(...) end
- end
- return handle
- end
- -- Checks if a path refers to an existing file or directory.
- function fs.exists(path)
- while path:sub(1, 1) == "/" do path = path:sub(2) end
- return oc_filesystem.exists(cc_save_directory.."/"..path) or oc_filesystem.exists(cc_lua_directory.."/"..path)
- end
- -- Checks if a path refers to an existing directory.
- function fs.isDir(path)
- while path:sub(1, 1) == "/" do path = path:sub(2) end
- return oc_filesystem.isDirectory(cc_save_directory.."/"..path) or oc_filesystem.isDirectory(cc_lua_directory.."/"..path)
- end
- -- Checks if a path is read-only (i.e. cannot be modified).
- function fs.isReadOnly(path)
- while path:sub(1, 1) == "/" do path = path:sub(2) end
- if oc_filesystem.exists(cc_lua_directory.."/"..path) and path:sub(1, 5):find("rom/") then
- return true
- end
- return path:sub(1, 4):find("rom") and true or false
- end
- -- Gets the final component of a pathname.
- function fs.getName(path)
- while path:sub(1, 1) == "/" do path = path:sub(2) end
- if path:sub(1, 5):find("rom/") then
- return oc_filesystem.name(cc_lua_directory.."/"..path)
- else
- return oc_filesystem.name(cc_save_directory.."/"..path)
- end
- end
- fs.name = fs.getName
- -- Gets the size of a file in bytes.
- function fs.getSize(path)
- while path:sub(1, 1) == "/" do path = path:sub(2) end
- if oc_filesystem.exists(cc_lua_directory.."/"..path) and path:sub(1, 5):find("rom/") then
- return oc_filesystem.size(cc_lua_directory.."/"..path)
- end
- return oc_filesystem.size(cc_save_directory.."/"..path)
- end
- -- Gets the remaining space on the drive containing the given directory.
- function fs.getFreeSpace(path)
- while path:sub(1, 1) == "/" do path = path:sub(2) end
- return oc_io.get(cc_save_directory.."/"..path).spaceFree()
- end
- local listCache = {}
- -- Returns a list of all the files (including subdirectories but not their contents) contained in a directory,
- -- as a numerically indexed table.
- function fs.list(path)
- --print(cc_lua_directory.."/"..path)
- if listCache[path] then
- return listCache[path]
- end
- local items = {}
- if oc_filesystem.isDirectory(cc_lua_directory.."/"..path) then
- for value in oc_filesystem.list(cc_lua_directory.."/"..path) do
- items[#items + 1] = value
- end
- end
- if oc_filesystem.isDirectory(cc_save_directory.."/"..path) then
- for value in oc_filesystem.list(cc_save_directory.."/"..path) do
- items[#items + 1] = value
- end
- end
- listCache[path] = items
- return items
- end
- -- Makes a directory.
- function fs.makeDir(path)
- while path:sub(1, 1) == "/" do path = path:sub(2) end
- oc_filesystem.makeDirectory(cc_save_directory.."/"..path)
- end
- -- Moves a file or directory to a new location.
- function fs.move(fromPath, toPath)
- oc_filesystem.move(cc_save_directory.."/"..fromPath, cc_save_directory.."/"..toPath)
- end
- -- Copies a file or directory to a new location.
- function fs.copy(fromPath, toPath)
- oc_filesystem.copy(cc_save_directory.."/"..fromPath, cc_save_directory.."/"..toPath)
- end
- -- Deletes a file or directory.
- function fs.delete(path)
- while path:sub(1, 1) == "/" do path = path:sub(2) end
- oc_filesystem.remove(cc_save_directory.."/"..path)
- end
- -- Combines two path components, returning a path consisting of the local path nested inside the base path.
- -- The resultant path consists of all the components of localPath inside all the components of basePath.
- -- Neither path needs to exist; this function only manipulates strings and does not touch the filesystem.
- function fs.combine(basePath, localPath)
- if #basePath > 0 and #localPath > 0 then
- return basePath.."/"..localPath
- elseif #basePath > 0 then
- return basePath
- elseif #localPath > 0 then
- return localPath
- end
- return ""
- end
- -- Searches the computer's files using wildcards.
- function fs.find(wildcard)
- local items = {}
- return items
- end
- -- Term API --
- local nativeTerm = term
- local termColors = {
- [1] = 0xF0F0F0,
- [2] = 0xF2B233,
- [4] = 0xE57FD8,
- [8] = 0x99B2F2,
- [16] = 0xDEDE6C,
- [32] = 0x7FCC19,
- [64] = 0xF2B2CC,
- [128] = 0x4C4C4C,
- [256] = 0x999999,
- [512] = 0x4C99B2,
- [1024] = 0xB266E5,
- [2048] = 0x3366CC,
- [4096] = 0x7F664C,
- [8192] = 0x57A64E,
- [16384] = 0xCC4C4C,
- [32768] = 0x000000
- }
- local charToTermColor = {}
- for value = 0, 15 do
- if value < 10 then
- charToTermColor[tostring(value)] = 2^value
- else
- charToTermColor[value == 10 and "a" or value == 11 and "b" or value == 12 and "c" or value == 13 and "d" or value == 14 and "e" or value == 15 and "f"] = 2^value
- end
- end
- local textColor = 1
- local backgroundColor = 32768
- gpu.setForeground(termColors[textColor] or 0xFFFFFF)
- gpu.setBackground(termColors[backgroundColor] or 0x000000)
- oc_term.clear()
- -- False functions in case it errors
- function term.native()
- return nativeTerm
- end
- function term.current()
- return nativeTerm
- end
- function term.redirect() end
- -- Actual functions begin
- function term.isColor()
- return gpu.getDepth() > 1
- end
- term.isColour = term.isColor
- function term.getTextColor()
- return textColor
- end
- function term.getBackgroundColor()
- return backgroundColor
- end
- function term.setTextColor(newColor)
- textColor = newColor
- gpu.setForeground(termColors[textColor] or 0xFFFFFF)
- end
- function term.setBackgroundColor(newColor)
- backgroundColor = newColor
- gpu.setBackground(termColors[backgroundColor] or 0x000000)
- end
- term.getTextColour = term.getTextColor
- term.getBackgroundColour = term.getBackgroundColor
- term.setTextColour = term.setTextColor
- term.setBackgroundColour = term.setBackgroundColor
- local cursorX, cursorY = 1, 1
- function term.getSize()
- return gpu.getResolution()
- end
- function term.getCursorPos()
- return cursorX, cursorY
- end
- function term.setCursorPos(x, y)
- cursorX, cursorY = math.max(x, 1), y
- oc_term.setCursor(cursorX, cursorY)
- end
- function term.setCursorBlink(newValue)
- return oc_term.setCursorBlink(newValue)
- end
- function term.scroll()
- local width, height = gpu.getResolution()
- local foregroundColor, backgroundColor = gpu.getForeground(), gpu.getBackground()
- -- Color correct copying
- for x = 1, width do
- local character, pixelForegroundColor, pixelBackgroundColor = gpu.get(x, height)
- if backgroundColor ~= pixelBackgroundColor then
- gpu.setBackground(pixelBackgroundColor)
- backgroundColor = pixelBackgroundColor
- end
- if foregroundColor ~= pixelForegroundColor then
- gpu.setForeground(pixelForegroundColor)
- foregroundColor = pixelForegroundColor
- end
- gpu.set(x, 0, character)
- end
- gpu.fill(1, height, width, 1, " ")
- end
- -- Writes text to the screen, using the current text and background colors.
- function term.write(text)
- gpu.set(cursorX, cursorY, text)
- cursorX = cursorX + #text
- oc_term.setCursor(cursorX, cursorY)
- end
- -- Writes text to the screen using the specified text and background colors. Requires version 1.74 or newer.
- function term.blit(text, colors, backgroundColors)
- if not #text == #colors then
- error("bad argument #2 to 'blit' (length of 'colors' must equal length of 'text')")
- elseif not #text == #backgroundColors then
- error("bad argument #3 to 'blit' (length of 'backgroundColors' must equal length of 'text')")
- end
- local lastBGColor = backgroundColor
- local lastFGColor = textColor
- for char = 1, #text do
- if lastBGColor ~= charToTermColor[backgroundColors:sub(char, char)] then
- lastBGColor = charToTermColor[backgroundColors:sub(char, char)]
- gpu.setBackground(termColors[charToTermColor[backgroundColors:sub(char, char)]])
- end
- if lastFGColor ~= charToTermColor[colors:sub(char, char)] then
- lastFGColor = charToTermColor[colors:sub(char, char)]
- gpu.setForeground(termColors[charToTermColor[colors:sub(char, char)]])
- end
- gpu.set(cursorX + char - 1, cursorY, text:sub(char, char))
- end
- cursorX = cursorX + #text
- oc_term.setCursor(cursorX, cursorY)
- end
- -- Clears the entire screen.
- function term.clear()
- oc_term.clear()
- oc_term.setCursor(cursorX, cursorY)
- end
- -- Clears the line the cursor is on.
- function term.clearLine()
- oc_term.clearLine()
- end
- -- OS API --
- -- Returns the unique ID of this computer. os.computerID() also behaves exactly the same as os.getComputerID().
- function os.getComputerID()
- return 0
- end
- --
- function os.getComputerLabel()
- return nil
- end
- --
- function os.setComputerLabel(label)
- end
- -- Adds an event to the event queue with the name event and the given parameters.
- function os.queueEvent(...)
- eventQueue[#eventQueue + 1] = {...}
- end
- -- Turns off the computer.
- function os.shutdown()
- oc_computer.shutdown(false)
- end
- -- Reboots the computer.
- function os.reboot()
- oc_computer.shutdown(true)
- end
- -- Queues an event to be triggered after a number of seconds (timeout).
- -- The ID of the timer is returned from this function to differentiate multiple timers.
- -- Timers are one-shot; once they have fired an event you will need to start another one if you need a recurring timer.
- function os.startTimer(timeout)
- local timerID = #timerList + 1
- -- Create the new timer
- timerList[timerID] = {Start = oc_computer.uptime(), Timeout = timeout, Canceled = false}
- return timerID
- end
- -- Cancels a running timer, to prevent it throwing an event.
- function os.cancelTimer(timerID)
- if timerList[timerID] then
- timerList[timerID].Canceled = true
- end
- end
- local getDayInGame = function()
- return math.floor(oc_os.time()/(60*60*24))
- end
- local getTimeInGame = function()
- return (oc_os.time()/(60*60))%24
- end
- -- Queues an event to be triggered at the specified in-game time.
- function os.startAlarm(time)
- local alarmID = #alarmList + 1
- -- Create the new alarm
- alarmList[alarmID] = {TimeOfDay = time, Canceled = false, FiredToday = getTimeInGame() > time}
- return alarmID
- end
- -- Cancels a pending alarm, to prevent it throwing an event.
- function os.cancelAlarm(alarmID)
- end
- -- Returns the amount of time since the in-game computer was started.
- function os.clock()
- return oc_computer.uptime()
- end
- -- Return the current in-game day (the number of in-game days since the world was created).
- function os.day()
- return getDayInGame()
- end
- -- Returns the current in-game time.
- function os.time()
- return getTimeInGame()
- end
- -- Redstone API --
- -- Returns a table of possible sides.
- function redstone.getSides()
- if oc_component.isAvailable("redstone") then
- --local oc_redstone = oc_component.redstone
- return {"left", "right", "top", "bottom", "front", "back"}
- end
- return {}
- end
- -- Returns the current redstone input signal state on side.
- function redstone.getInput(side)
- if oc_component.isAvailable("redstone") then
- local oc_redstone = oc_component.redstone
- if oc_sides[side] then
- local value = oc_redstone.getInput(oc_sides[side])
- return value > 0
- end
- end
- end
- function redstone.getOutput(side)
- if oc_component.isAvailable("redstone") then
- local oc_redstone = oc_component.redstone
- if oc_sides[side] then
- local value = oc_redstone.getOutput(oc_sides[side])
- return value > 0
- end
- end
- end
- function redstone.getOutput(side)
- if oc_component.isAvailable("redstone") then
- local oc_redstone = oc_component.redstone
- if oc_sides[side] then
- local value = oc_redstone.getOutput(oc_sides[side])
- return value > 0
- end
- end
- end
- function redstone.setOutput(side, value)
- if oc_component.isAvailable("redstone") then
- local oc_redstone = oc_component.redstone
- if oc_sides[side] then
- pcall(oc_redstone.setOutput, oc_sides[side], 255)
- pcall(oc_redstone.setOutput, oc_sides[side], 15)
- end
- end
- end
- function redstone.getAnalogInput(side)
- if oc_component.isAvailable("redstone") then
- local oc_redstone = oc_component.redstone
- if oc_sides[side] then
- return oc_redstone.getInput(oc_sides[side])
- end
- end
- end
- function redstone.getAnalogOutput(side)
- if oc_component.isAvailable("redstone") then
- local oc_redstone = oc_component.redstone
- if oc_sides[side] then
- return oc_redstone.getOutput(oc_sides[side])
- end
- end
- end
- function redstone.setAnalogOutput(side, value)
- if oc_component.isAvailable("redstone") then
- local oc_redstone = oc_component.redstone
- if oc_sides[side] then
- oc_redstone.setOutput(oc_sides[side], value)
- end
- end
- end
- -- Rednet API --
- function rednet.run()
- while true do
- coroutine.yield()
- end
- end
- -- HTTP API --
- if oc_component.isAvailable("internet") then
- if oc_component.internet.isHttpEnabled() then
- local internet = oc_component.internet
- http = {}
- function http.request(url, postData, headers)
- local realHandle = internet.request(url, postData)
- local handle = {}
- function handle.close() realHandle:close() end
- function handle.readLine() return realHandle:read() end
- function handle.readAll() return realHandle:read("*a") end
- function handle.getResponseCode()
- local responseCode = realHandle:response()
- return responseCode
- end
- eventQueue[#eventQueue + 1] = {"http_success", url, handle}
- end
- function http.checkURL(url)
- return true
- end
- end
- end
- -- A function useful for completing the envirornment
- local cloneTable
- cloneTable = function(tableToClone)
- local clonedTable = {}
- for key, value in pairs(tableToClone) do
- if type(value) == "table" then
- clonedTable[key] = cloneTable(value)
- else
- clonedTable[key] = value
- end
- end
- return clonedTable
- end
- -- Complete the envirornment
- ccEnv.print = print
- ccEnv.load = load
- ccEnv.loadstring = load
- ccEnv.type = type
- ccEnv.select = select
- ccEnv.next = next
- ccEnv.pairs = pairs
- ccEnv.ipairs = ipairs
- ccEnv.assert = assert
- ccEnv.error = error
- ccEnv.getmetatable = getmetatable
- ccEnv.setmetatable = setmetatable
- ccEnv.pcall = pcall
- ccEnv.xpcall = xpcall
- ccEnv.tostring = tostring
- ccEnv.tonumber = tonumber
- ccEnv.setfenv = setfenv
- ccEnv.getfenv = getfenv
- ccEnv.unpack = table.unpack
- if not ccEnv.setfenv then
- function ccEnv.setfenv(thisfunction, env)
- local oldFunction = thisfunction
- thisfunction = function(...)
- local _ENV = env
- return oldFunction(...)
- end
- return thisfunction
- end
- function ccEnv.getfenv(x)
- return _ENV
- end
- end
- -- Add the APIs.
- ccEnv.fs = fs
- ccEnv.os = os
- ccEnv.term = term
- ccEnv.redstone = redstone
- ccEnv.rs = redstone
- ccEnv.rednet = rednet
- ccEnv.http = http
- ccEnv.bit = cloneTable(bit32)
- ccEnv.string = cloneTable(string)
- ccEnv.table = cloneTable(table)
- --ccEnv.table.unpack = nil
- ccEnv.math = cloneTable(math)
- ccEnv.coroutine = cloneTable(coroutine)
- for key, value in pairs(ccEnv) do
- if key ~= "_G" or key ~= "_ENV" then
- ccEnv._G[key] = value
- ccEnv._ENV[key] = value
- end
- end
- -- Install the character key to character converter
- local characterKeysString = "abcdefghijklmnopqrstuvwxyz1234567890"
- local characterKeyToString = {
- [oc_keyboard.keys.space] = " ",
- [oc_keyboard.keys.apostrophe] = "'",
- [oc_keyboard.keys.slash] = "/",
- [oc_keyboard.keys.backslash] = "\\",
- [oc_keyboard.keys.lbracket] = "[",
- [oc_keyboard.keys.rbracket] = "]",
- [oc_keyboard.keys.equals] = "=",
- [oc_keyboard.keys.minus] = "-",
- [oc_keyboard.keys.colon] = ";",
- [oc_keyboard.keys.comma] = ",",
- [oc_keyboard.keys.period] = ".",
- [oc_keyboard.keys.numpadsub] = "-",
- [oc_keyboard.keys.numpadadd] = "+",
- }
- for char = 1, #characterKeysString do
- characterKeyToString[oc_keyboard.keys[characterKeysString:sub(char,char)]] = characterKeysString:sub(char,char)
- end
- local characterKeyToStringUpper = {
- [oc_keyboard.keys["1"]] = "!",
- [oc_keyboard.keys["2"]] = "@",
- [oc_keyboard.keys["3"]] = "#",
- [oc_keyboard.keys["4"]] = "$",
- [oc_keyboard.keys["5"]] = "%",
- [oc_keyboard.keys["6"]] = "^",
- [oc_keyboard.keys["7"]] = "&",
- [oc_keyboard.keys["8"]] = "*",
- [oc_keyboard.keys["9"]] = "(",
- [oc_keyboard.keys["0"]] = ")",
- [oc_keyboard.keys.apostrophe] = "\"",
- [oc_keyboard.keys.slash] = "?",
- [oc_keyboard.keys.backslash] = "|",
- [oc_keyboard.keys.lbracket] = "{",
- [oc_keyboard.keys.rbracket] = "}",
- [oc_keyboard.keys.equals] = "+",
- [oc_keyboard.keys.minus] = "_",
- [oc_keyboard.keys.colon] = ":",
- [oc_keyboard.keys.comma] = ",",
- [oc_keyboard.keys.period] = ">",
- }
- -- Run the bios script
- local biosScript = assert(loadfile(cc_lua_directory.."/bios.lua", ccEnv, ccEnv))
- local bios = function()
- local success, errorMessage = xpcall(function()
- local ccEnv = ccEnv
- local _ENV = ccEnv
- _G = ccEnv
- biosScript()
- end,
- function(errorMessage)
- return errorMessage.."\n"..debug.traceback()
- end)
- if not success then
- error(errorMessage, 0)
- end
- end
- local computerCoroutine = coroutine.create(bios)
- local computerOn = true
- local lastTimeInGame = getTimeInGame()
- function os.shutdown()
- computerOn = false
- end
- while computerOn do
- local oc_Signal = {oc_event.pull(0)}
- -- Handle the OpenComputers signal
- if oc_Signal then
- if oc_Signal[1] == "key_down" then
- if characterKeyToString[oc_Signal[4]] then
- if oc_keyboard.isShiftDown() then
- if characterKeyToStringUpper[oc_Signal[4]] then
- eventQueue[#eventQueue + 1] = {"char", characterKeyToStringUpper[oc_Signal[4]]}
- else
- eventQueue[#eventQueue + 1] = {"char", string.upper(characterKeyToString[oc_Signal[4]])}
- end
- else
- eventQueue[#eventQueue + 1] = {"char", characterKeyToString[oc_Signal[4]]}
- end
- end
- eventQueue[#eventQueue + 1] = {"key", oc_Signal[4]}
- elseif oc_Signal[1] == "key_up" then
- eventQueue[#eventQueue + 1] = {"key_up", oc_Signal[4]}
- elseif oc_Signal[1] == "touch" then
- eventQueue[#eventQueue + 1] = {"mouse_click", oc_Signal[5], oc_Signal[3], oc_Signal[4]}
- elseif oc_Signal[1] == "drop" then
- eventQueue[#eventQueue + 1] = {"mouse_up", oc_Signal[5], oc_Signal[3], oc_Signal[4]}
- elseif oc_Signal[1] == "drag" then
- eventQueue[#eventQueue + 1] = {"mouse_drag", oc_Signal[5], oc_Signal[3], oc_Signal[4]}
- elseif oc_Signal[1] == "screen_resized" then
- eventQueue[#eventQueue + 1] = {"term_resize"}
- end
- end
- -- Try to terminate anything
- if oc_keyboard.isControlDown() and oc_keyboard.isKeyDown(0x14) then
- table.insert(eventQueue, 1, {"terminate"})
- --table.insert(eventQueue, "terminate")
- end
- -- Handle timers and alarms
- for timerID, timer in ipairs(timerList) do
- if not timer.Canceled then
- if oc_computer.uptime() > timer.Start + timer.Timeout then
- -- Trigger the timer event
- timer.Canceled = true -- Timers are one-shot, therfore it must be "canceled" after it fires.
- eventQueue[#eventQueue + 1] = {"timer", timerID}
- end
- end
- end
- if getTimeInGame() < lastTimeInGame then
- for alarmID, alarm in ipairs(alarmList) do
- if not alarm.Canceled then
- -- Untrigger the alarm event
- alarm.FiredToday = false
- end
- end
- end
- for alarmID, alarm in ipairs(alarmList) do
- if getTimeInGame() > alarm.Time and not alarm.Canceled and not alarm.FiredToday then
- -- Trigger the alarm event
- alarm.FiredToday = true
- eventQueue[#eventQueue + 1] = {"alarm", timerID}
- end
- end
- -- Update the ComputerCraft emulation state
- if not eventQueue[1] then
- assert(coroutine.resume(computerCoroutine))
- else
- assert(coroutine.resume(computerCoroutine, eventQueue[1][1], eventQueue[1][2], eventQueue[1][3], eventQueue[1][4], eventQueue[1][5], eventQueue[1][6], eventQueue[1][7], eventQueue[1][8], eventQueue[1][9], eventQueue[1][10]))
- table.remove(eventQueue, 1)
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement