Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Paths to data files
- local sPasswordPath = "/.password"
- local sDataPath = "/.data"
- -- functions to read/write to/from a file
- local function writeToFile(sFilename, sData)
- local file = io.open(sFilename, 'w') -- open the file in write (w) mode
- file:write(sData):close() -- write the data then close it
- end
- local function readFromFile(sFilename)
- local file = io.open(sFilename, 'r') -- open the file in read (r) mode
- local sData = file:read("*a") -- read all (*a)
- file:close() -- close it
- return sData -- return the data read
- end
- -- check if the data files exist, and if not, write defaults.
- -- default password is 'admin', default redstone output side is 'top'
- if not fs.exists(sPasswordPath) then
- writeToFile(sPasswordPath, "admin")
- end
- if not fs.exists(sDataPath) then
- writeToFile(sDataPath, "top")
- end
- -- get the data from the files
- local sPassword = readFromFile(sPasswordPath)
- local sSide = readFromFile(sDataPath)
- --[[
- key resolver table, keys in the 'keys' table are stored as a number
- and the values differ from version to version.
- With these resolver tables, I can index the table via tKeyResolver[key] and
- get a value from 1-9.
- ]]
- -- 1-9 on top
- local tKeyResolver = {
- [keys.one] = 1,
- [keys.two] = 2,
- [keys.three] = 3,
- [keys.four] = 4,
- [keys.five] = 5,
- [keys.six] = 6,
- [keys.seven] = 7,
- [keys.eight] = 8,
- [keys.nine] = 9
- }
- -- numpad
- local tKeyResolver2 = {
- [keys.numPad1] = 1,
- [keys.numPad2] = 2,
- [keys.numPad3] = 3,
- [keys.numPad4] = 4,
- [keys.numPad5] = 5,
- [keys.numPad6] = 6,
- [keys.numPad7] = 7,
- [keys.numPad8] = 8,
- [keys.numPad9] = 9
- }
- -- display the table of information, and if sEvent is given, add that to the bottom.
- local function display(tInfo, sEvent)
- -- clear the screen.
- term.setBackgroundColor(colors.black)
- term.setTextColor(colors.white)
- term.clear()
- term.setCursorPos(1, 1)
- -- tell the user what options there are
- print("Select one of the following:")
- for i = 1, #tInfo do -- for i = 1 to n where n is the length of tInfo
- print(string.format("%d: %s", i, tInfo[i]))
- -- print the number, and the string in the table at that value
- end
- -- if an event occured and was passed to this function, print it.
- if sEvent then
- print("\n")
- print(sEvent)
- end
- -- Loop to listen for 1-9 on keyboard or numpad
- while true do
- -- pull event RAW to bypass terminate
- local sEvent, iKey = os.pullEventRaw("key")
- if tKeyResolver[iKey] and tKeyResolver[iKey] <= #tInfo then
- -- if the key is part of 1-9 on the keyboard, and one of the options correspond to the value hit, return the value hit.
- return tKeyResolver[iKey]
- end
- if tKeyResolver2[iKey] and tKeyResolver2[iKey] <= #tInfo then
- -- if the key is part of 1-9 on the numpad, and one of the options correspond to the value hit, return the value hit.
- return tKeyResolver2[iKey]
- end
- end
- end
- -- sleeps using pullEventRaw instead of pullEvent to bypass termination
- local function safeSleep(fSeconds)
- -- start a timer for the time inputted
- -- (os.startTimer will queue a timer event after fSeconds seconds.)
- local iTimer = os.startTimer(fSeconds)
- while true do
- -- wait for our timer event from the os
- local sEvent, iT = os.pullEventRaw("timer")
- if iTimer == iT then
- -- once we recieve the timer event, return
- return
- end
- end
- end
- -- create a table of functions which correspond to an option in the display call
- -- for example, tFuncs[1]() opens the door, tFuncs[2]() closes the door, and so on...
- -- these functions used in the function "loggedIn"
- local tFuncs = {
- function() -- Open door
- redstone.setOutput(sSide, true)
- last = "Door opened." -- on the next iteration, tell the user the door was opened
- end,
- function() -- Close door
- redstone.setOutput(sSide, false)
- last = "Door closed." -- on the next iteration, tell the user the door was opened
- end,
- function() -- change redstone output side
- local tSides = redstone.getSides()
- local iVal = display(tSides) -- display all sides you can output redstone from, and let the user choose one.
- sSide = tSides[iVal] -- set the redstone output side locally (in RAM)
- writeToFile(sDataPath, sSide) -- save the side so if the computer reboots it doesn't set itself back to default values
- last = string.format("Redstone output side set to '%s'", sSide) -- tell the user the side was set.
- end,
- function() -- change password
- -- clear the screen
- term.clear()
- term.setCursorPos(1, 1)
- safeSleep(0.05) -- wait a short bit, for some reason events above here get passed to read so an extra character gets added
- -- get the user's password twice, to ensure they entered it correctly
- term.write("Enter new password: ")
- local sPass1 = read("*")
- term.setCursorPos(1, 2)
- safeSleep(0.05) -- wait a short bit, for some reason events above here get passed to read so an extra character gets added
- term.write("Confirm password : ")
- local sPass2 = read("*")
- -- if the passwords match, save the password and set the new password in RAM
- -- otherwise let the user know the password set failed
- if sPass1 == sPass2 then
- writeToFile(sPasswordPath, sPass1)
- sPassword = sPass1
- last = "Password has been changed."
- else
- last = "Password change failed: Passwords did not match."
- end
- end
- }
- -- logged in menu page, does all the stuff once you're logged in
- local function loggedIn()
- local last -- declared here so it's persistant between loop iterations
- -- main loop to listen for user input and do things
- while true do
- -- display the options and get what the user chooses
- local iVal = display({
- "Open door",
- "Close door",
- "Change redstone output side",
- "Change password",
- "Log out"
- }, last)
- -- if the function exists, then call the function
- if tFuncs[iVal] then
- tFuncs[iVal]()
- elseif iVal == 5 then
- -- if it does not exist, and we hit 5 (log out), then return to the last function (aka log out)
- return
- end
- end
- end
- local function main()
- -- main loop
- while true do
- -- wait for user to login
- display({"Login"})
- safeSleep(0.05) -- wait a short bit, for some reason events above here get passed to read so an extra character gets added
- -- request password
- term.clear()
- term.setCursorPos(1, 1)
- print("Enter your password.")
- local sRead = read("*")
- -- if the password the user entered matches the password we have stored
- if sRead == sPassword then
- -- show the logged in screen
- loggedIn()
- -- then clear the screen, and let the user know we logged them out.
- term.clear()
- term.setCursorPos(1, 1)
- print("Logged out.")
- safeSleep(2)
- else
- -- if incorrect, let user know.
- term.clear()
- term.setCursorPos(1, 1)
- printError("Incorrect password.")
- safeSleep(2)
- end
- end
- end
- -- read() uses os.pullEvent, so terminate events can get through during password entry
- -- if someone does terminate (or some other error occurs) the error will be printed here,
- -- and the computer will reboot.
- local ok, err = pcall(main)
- if not ok then
- printError("An error occured:")
- printError(err)
- end
- print("Rebooting...")
- safeSleep(2)
- os.reboot()
Add Comment
Please, Sign In to add comment