SHOW:
|
|
- or go back to the newest paste.
| 1 | -- Passlock v0 | |
| 2 | -- (C) 2012 User 'Advert' at http://www.computercraft.info/forums2/ | |
| 3 | -- X11/mit licence (use/modify at your will, but please, leave credit where due) | |
| 4 | ||
| 5 | -- Settings. | |
| 6 | local dConfig = {} -- Marking defaults, so we can revert to them easily.
| |
| 7 | ||
| 8 | do -- Because I like do statements. | |
| 9 | dConfig["sUserPassword"] = "open" | |
| 10 | dConfig["sRootPassword"] = "2good4u" | |
| 11 | dConfig["nOpenTime"] = 3 -- Number of seconds to keep the door open. | |
| 12 | dConfig["nUserPassFailLock"]= 3 -- Number of user password fails before lock. (0 = disable, 1 = 1 fail, 2 = 2 fails, etc.) Reset at success (root can still login) | |
| 13 | dConfig["nUserPassFailLockDuration"] = 15 -- Number of seconds to lock after nUserPassFailLock password fails | |
| 14 | dConfig["bRootForceOpen"] = false -- Door is forced open by Root user. | |
| 15 | dConfig["bLockAtStartup"] = true -- This will lock the computer for nUserPassFailLockDuration seconds at startup, to prevent bypassing of nUserLockPassFailLock. | |
| 16 | dConfig["sRedstoneSide"] = "back" -- The side the redstone is at. | |
| 17 | -- Stuff not stored here: door state, etc. | |
| 18 | end | |
| 19 | -- small helper function ;_; | |
| 20 | local function copyTable(o) | |
| 21 | -- Will simply copy a table, non-recursively. | |
| 22 | local t = {}
| |
| 23 | for k, v in pairs(o) do t[k] = v end | |
| 24 | return t | |
| 25 | end | |
| 26 | ||
| 27 | local config = copyTable(dConfig) | |
| 28 | local bRootExit = false | |
| 29 | local bDoorState = true -- true = locked. | |
| 30 | local nUserAttempts = 0 | |
| 31 | local nUserLastAttempt = 0 | |
| 32 | -- Misc functions | |
| 33 | ||
| 34 | local function mergeTable(t1, t2) | |
| 35 | -- This function puts everyting in t2 into t1. | |
| 36 | for k, v in pairs(t2) do | |
| 37 | t1[k] = v | |
| 38 | end | |
| 39 | return t1 -- We return t1 because that's the table you'll want afterwards (even though it doesn't make a new table) | |
| 40 | end | |
| 41 | ||
| 42 | -- Major functions | |
| 43 | -- Making functions local (I don't like messing up _G) | |
| 44 | local renderDisplay, checkEvents, loadFromFile, saveToFile | |
| 45 | local checkDoorTimer, checkUserLockTimer | |
| 46 | -- Core loop components | |
| 47 | function renderDisplay() | |
| 48 | -- Frame timer | |
| 49 | os.startTimer(0.2) -- 5 fps is good enough, can even do less, but meh. | |
| 50 | - | function checkEvents() |
| 50 | + | -- Clean the terminal |
| 51 | term.clear() | |
| 52 | - | local event, p1, p2 = os.pullEvent() |
| 52 | + | |
| 53 | ||
| 54 | - | print("Event: ", event, "\n p1 & p2: ", p1, ",", p2)
|
| 54 | + | |
| 55 | --TODO | |
| 56 | end | |
| 57 | ||
| 58 | -- | |
| 59 | function checkEvents(event, p1, p2) | |
| 60 | -- Used in our loop to check for new OS events. | |
| 61 | if event == "char" then | |
| 62 | if p1 == "x" then | |
| 63 | error("User pressed 'x'. 'x' is a bad key to press.")
| |
| 64 | elseif p1 == "s" then | |
| 65 | saveToFile() | |
| 66 | loadFromFile() | |
| 67 | end | |
| 68 | end | |
| 69 | ||
| 70 | end | |
| 71 | ||
| 72 | function checkDoorTimer() | |
| 73 | --TODO | |
| 74 | end | |
| 75 | ||
| 76 | function checkUserLockTimer() | |
| 77 | --TODO | |
| 78 | end | |
| 79 | ||
| 80 | -- Door toggler. | |
| 81 | function toggleDoor(bState) | |
| 82 | -- This will toggle the door, or set it's state to bState | |
| 83 | if bState ~= nil then | |
| 84 | bDoorState = bState | |
| 85 | else | |
| 86 | bDoorState = not bDoorState -- not negates the state in boolean: true, any data not nil -> false; false, nil -> true | |
| 87 | end | |
| 88 | return bDoorState -- Good practice to return result, in this case the door's state. | |
| 89 | end | |
| 90 | ||
| 91 | ||
| 92 | - | local err, res = pcall(dofile, "passlock-data") -- Yes, I'm doing this the easy and hard way. |
| 92 | + | |
| 93 | - | if err then |
| 93 | + | |
| 94 | do -- This just to make the code neater, really. (And so I can easily collapse the code in ScITE) | |
| 95 | ||
| 96 | function loadFromFile() | |
| 97 | if not fs.exists("passlock-data") then return end -- We can't load nothing.
| |
| 98 | local err, res = pcall(function() return loadfile("passlock-data")() end) -- Yes, I'm doing this the easy and hard way.
| |
| 99 | if not err then | |
| 100 | print("Error loading configuration: \n", res)
| |
| 101 | print("Enter to continue...")
| |
| 102 | - | local saveAs = {}
|
| 102 | + | |
| 103 | - | saveAs.boolean = [[config[%q] = %s]] |
| 103 | + | |
| 104 | - | saveAs.string = [[config[%q] = %q]] |
| 104 | + | |
| 105 | - | saveAs.number = [[config[%q] = %d]] |
| 105 | + | |
| 106 | ||
| 107 | -- Saving helper format strings | |
| 108 | local saveHelper = {}
| |
| 109 | saveHelper.boolean = [[config[%q] = %s]] | |
| 110 | saveHelper.string = [[config[%q] = %q]] | |
| 111 | - | local sData = [[local config = {} -- This file, generated by Passlock. Edit at your own risk.\n]]
|
| 111 | + | saveHelper.number = [[config[%q] = %d]] |
| 112 | ||
| 113 | -- Saving function | |
| 114 | function saveToFile() | |
| 115 | -- This is the 'harder' part of the two :( | |
| 116 | ||
| 117 | local sData = [[local config = {} -- This file, generated by Passlock. Edit at your own risk.]] .. "\n"
| |
| 118 | ||
| 119 | for k, v in pairs(config) do | |
| 120 | local sDataType = type(v) | |
| 121 | - | sData = sData .. string.format(sSaveHelper, k, v) .. "\n" |
| 121 | + | |
| 122 | if not sSaveHelper then | |
| 123 | -- We have problem, let's just print it, and continue without saving it. | |
| 124 | print("Warning: (saveToFile) unknown data type, in key: " .. k)
| |
| 125 | else | |
| 126 | -- No errors, save it. | |
| 127 | sData = sData .. string.format(sSaveHelper, k, tostring(v)) .. "\n" | |
| 128 | end | |
| 129 | end | |
| 130 | ||
| 131 | - | local hHandle = fs.open("passlock-data", "w")
|
| 131 | + | |
| 132 | -- Delete and save. | |
| 133 | if fs.exists("passlock-data") then
| |
| 134 | fs.delete("passlock-data")
| |
| 135 | end | |
| 136 | local hHandle = io.open("passlock-data", "w")
| |
| 137 | if not hHandle then | |
| 138 | -- We're pissed, let's error. | |
| 139 | error("Unable to open file handle; call to saveToFile", 2)
| |
| 140 | end | |
| 141 | hHandle:write(sData) | |
| 142 | hHandle:close() | |
| 143 | end | |
| 144 | end | |
| 145 | ||
| 146 | ||
| 147 | -- Looping function | |
| 148 | - | checkDoorTimer() -- Lock the door if it has been open long enough |
| 148 | + | |
| 149 | - | checkUserLockTimer() -- Allow user to login again, if enough time has passed. |
| 149 | + | |
| 150 | - | --renderDisplay() -- We need to see something. |
| 150 | + | |
| 151 | - | checkEvents() -- Get our user input, or yet another timer event for updating the screen. |
| 151 | + | |
| 152 | end | |
| 153 | local event, p1, p2 = os.pullEvent() | |
| 154 | print("Event: ", event, "\n p1 & p2: ", p1, ",", p2)
| |
| 155 | if event == "timer" then | |
| 156 | checkDoorTimer() -- Lock the door if it has been open long enough | |
| 157 | checkUserLockTimer() -- Allow user to login again, if enough time has passed. | |
| 158 | renderDisplay() -- Moved inside checkEvents, to provide a static #FPS (i.e typing will cause an overload of timers) | |
| 159 | end | |
| 160 | checkEvents(event, p1, p2) -- Get our user input, or yet another timer event for updating the screen. | |
| 161 | -- Doesn't seem like much, does it? D: | |
| 162 | end | |
| 163 | end | |
| 164 | ||
| 165 | - | if err ~= true then |
| 165 | + | |
| 166 | - | print("error: ", string.format("%q", res))
|
| 166 | + | -- Startup function, one-time. |
| 167 | - | print("enter to continue... (ctrl-t is SUPER EFFECTIVE right now!)")
|
| 167 | + | function startup() |
| 168 | - | read() |
| 168 | + | loadFromFile() -- Loads config if it exists. |
| 169 | end | |
| 170 | ||
| 171 | -- Loop | |
| 172 | while true do | |
| 173 | local err, res = pcall(doImportantStuff) | |
| 174 | if bRootExit then -- Quit if user logged in as Root wishes to. | |
| 175 | break | |
| 176 | end | |
| 177 | if not err then | |
| 178 | if res ~= "Terminated" then | |
| 179 | print("error: ", string.format("%q", res))
| |
| 180 | print("enter to continue... (ctrl-t is SUPER EFFECTIVE right now!)")
| |
| 181 | read() | |
| 182 | end | |
| 183 | end | |
| 184 | end |