Advertisement
Rihlsul

ElevatorControl Cabin 1.03

Apr 18th, 2013
127
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 15.23 KB | None | 0 0
  1. local version = 1.03
  2. -- SPECIAL ROOF TRAP EDITION --
  3.  
  4. local CabinConfig = {}
  5. local CabinScreen = {}
  6. local cabinSettingsFile = "Cabin.Settings"
  7.  
  8. local floorDescs = { }
  9. local floorLines = { }
  10. local floorPass = { }
  11.    
  12. local KeepWaiting = true
  13. local Unlocked = true
  14. local relockAlarm = nil
  15.  
  16. -- ######################################################
  17. -- ##  Load the API                                    ##
  18. -- ######################################################
  19.  
  20. if fs.exists("ECAPI") then --Check to make sure that the entered API exists
  21.   os.loadAPI("ECAPI")
  22.   print("ECAPI loaded.")
  23. else
  24.   print("That API does not exist.  Retrieving from PasteBin")
  25.   -- we get it automagically
  26.   shell.run("pastebin","get", "1mcEVzzP", "ECAPI")
  27.   os.loadAPI("ECAPI")
  28.   print("ECAPI loaded.")
  29. end
  30.  
  31.  
  32. -- ######################################################
  33. -- ##  Setup Configuration                             ##
  34. -- ######################################################
  35.  
  36. local DefaultConfig = {}
  37. DefaultConfig = ECAPI.addConfigOption(DefaultConfig,"Version",version,"Please do not change this.")
  38. DefaultConfig = ECAPI.addConfigOption(DefaultConfig,"Network","","Elevator network name:")
  39. DefaultConfig = ECAPI.addConfigOption(DefaultConfig,"Modem","","Which side is the modem?",'side')
  40. DefaultConfig = ECAPI.addConfigOption(DefaultConfig,"Intro","Please enter a # or X to exit.","User Message:")
  41. DefaultConfig = ECAPI.addConfigOption(DefaultConfig,"Floor","Floor","Term for floor?")
  42. DefaultConfig = ECAPI.addConfigOption(DefaultConfig,"Description","Description","Term for floor descriptions?")
  43. DefaultCongig = ECAPI.addConfigOption(DefaultConfig,"PWTag","SECURE","Tag for secure floors?")
  44. DefaultCongig = ECAPI.addConfigOption(DefaultConfig,"PWShow","","Show secure floors [true/false]?")
  45. DefaultConfig = ECAPI.addConfigOption(DefaultConfig,"AccessPW","","Access Password:",'pass')
  46. DefaultConfig = ECAPI.addConfigOption(DefaultConfig,"ConfigPW","","Config. Password:",'pass')   -- note, this is per machine
  47. DefaultConfig = ECAPI.addConfigOption(DefaultConfig,"Invalid","","Side to activate on invalid password",'side')
  48.  
  49. local function networkName()
  50.     return ECAPI.getConfigOption(CabinConfig,"Network")
  51. end
  52.  
  53. local function modemSide()
  54.     return ECAPI.getConfigOption(CabinConfig,"Modem")
  55. end
  56.  
  57. local function floorDesc()
  58.     return ECAPI.getConfigOption(CabinConfig,"Floor")
  59. end
  60.  
  61.  
  62. -- ######################################################
  63. -- ##  Terminal Functions                              ##
  64. -- ######################################################
  65.  
  66. local function termClear()
  67.     ECAPI.printCabinTemplate(CabinConfig)
  68.     CabinScreen = ECAPI.setupScreen(CabinScreen)
  69.     term.setCursorPos(3,18)
  70.     local prompt = ""
  71.     if Unlocked then
  72.         prompt = "Command:"
  73.     else
  74.         prompt = ECAPI.getConfigPrompt(CabinConfig,"AccessPW")
  75.     end
  76.     write(prompt)
  77.     term.setCursorPos(3+string.len(prompt)+1,18)
  78. end
  79.  
  80. local function justPrintLine(newLine)
  81.     if Unlocked then
  82.         CabinScreen = ECAPI.justPrintLine(CabinScreen,newLine)
  83.     end
  84. end
  85.  
  86. local function printFloors(floorDescTable)
  87.     if (floorDescTable ~= nil) then
  88.         local rawTable = textutils.unserialize(floorDescTable)
  89.         for flID, flSettings in pairs(rawTable) do
  90.             floorDescs[flID] = flSettings["Description"]
  91.             if (flSettings['Password'] ~= "") then
  92.                 floorPass[flID] = flSettings['Password']
  93.             end
  94.         end
  95.     end
  96.     termClear()
  97.     term.setCursorPos(1,6)
  98.     if (ECAPI.table_count(floorDescs)) > 0 then
  99.         --print("if check")
  100.         local preX, preY = 0, 0
  101.         for fl,desc in ECAPI.ripairs(floorDescs) do
  102.             preX, preY = term.getCursorPos()
  103.             floorLines[fl] = preY
  104.             local tag = ""
  105.             if (floorPass[fl] ~= nil) and (floorPass[fl] ~= "") then
  106.                 -- There IS a floor password.  Tag setting
  107.                 tag = "["..ECAPI.getConfigOption(CabinConfig,"PWTag").."] "
  108.                 --Should we or should we not print it?
  109.                 if (string.lower(ECAPI.getConfigOption(CabinConfig,"PWShow")) ~= "true") then
  110.                     -- assume DON'T
  111.                 else
  112.                     if Unlocked then ECAPI.printLine("|  "..ECAPI.padRight(fl,4,' ').." | "..ECAPI.padLeft(tag..desc,40,' ').."|") end
  113.                 end
  114.             else
  115.                 if Unlocked then ECAPI.printLine("|  "..ECAPI.padRight(fl,4,' ').." | "..ECAPI.padLeft(desc,40,' ').."|") end
  116.             end
  117.         end
  118.         if (preY < 15) then
  119.             --ElevatorControlAPI.printLine(divider)
  120.             for i = preY,15 do
  121.                 if Unlocked then ECAPI.printLine("|  "..ECAPI.padRight("",4,' ').." | "..ECAPI.padLeft("",40,' ').."|") end
  122.             end
  123.         end
  124.     else
  125.         if Unlocked then ECAPI.printLine("* No Floor computers registered. *") end
  126.     end
  127.     if Unlocked then ECAPI.printLine("") end
  128.     term.setCursorPos(12,18)
  129.     -- Any time we redraw the floors, we'll need to 'relocate' the cabin
  130.     ECAPI.broadcast(networkName(),'locate')
  131. end
  132.  
  133. function changeUpdate(output)
  134.     local oldX, oldY = term.getCursorPos()
  135.     term.setCursorPos(10,16)
  136.     if Unlocked then write(ECAPI.padLeft(output,40," ")) end
  137.     os.sleep(.25)
  138.     term.setCursorPos(10,16)
  139.     if Unlocked then write(ECAPI.padLeft(" ",40," ")) end
  140.     term.setCursorPos(oldX,oldY)
  141. end
  142.  
  143. local function updateFloor(floorID,indicator)
  144.     local oldX, oldY = term.getCursorPos()
  145.     for i = 6,15 do
  146.         term.setCursorPos(2,i)
  147.         if Unlocked then write("  ") end
  148.     end
  149.     if (floorLines ~= nil) and (ECAPI.table_count(floorLines) > 0) and (floorID ~= nil) then
  150.         term.setCursorPos(2,floorLines[tonumber(floorID)])
  151.         if Unlocked then write(indicator) end
  152.     end
  153.     term.setCursorPos(oldX, oldY)
  154. end
  155.  
  156. local function openDoor()
  157.     ECAPI.broadcast(networkName(),'openfloor')
  158. end
  159.  
  160. local function selectFloor(whichFloor)
  161.     ECAPI.broadcast(networkName(),'opendoor|invalid|') -- forces all doors closed
  162.     ECAPI.broadcast(networkName(),'request|'..whichFloor)
  163. end
  164.  
  165.  local function reconfig(args)
  166.     if (ECAPI.checkPassword(CabinScreen,CabinConfig,"ConfigPW")) then
  167.         local what = args[1]
  168.         if (what == nil) or (what == "") then
  169.             CabinConfig = DefaultConfig
  170.             createNewSettings()
  171.         else
  172.             what = ECAPI.caseCheck(CabinConfig,what)
  173.             if (args[2] == nil) then
  174.                 CabinScreen, CabinConfig = ECAPI.getConfigFromUser(CabinScreen,CabinConfig,what)
  175.             else
  176.                 CabinConfig = ECAPI.setConfigOption(CabinConfig,what,table.concat(args," ",2))
  177.             end
  178.             -- Make sure to SAVE changes
  179.             ECAPI.table_save(CabinConfig,cabinSettingsFile)
  180.            
  181.             ECAPI.openModem(modemSide())
  182.         end
  183.     else
  184.         local badSide = ECAPI.getConfigOption(CabinConfig,"Invalid")
  185.         if (badSide == "") then
  186.             changeUpdate("Invalid password.")
  187.         else
  188.             changeUpdate("Wrong password.  Goodbye.")
  189.             os.sleep(0.2)
  190.             redstone.setOutput(badSide,false)
  191.             os.sleep(60)
  192.             redstone.setOutput(badSide,true)
  193.         end
  194.     end
  195. end
  196.  
  197.  
  198. -- ######################################################
  199. -- ##  Settings Functions                              ##
  200. -- ######################################################
  201.  
  202. local function createNewSettings()
  203.  
  204.     CabinConfig = DefaultConfig
  205.     termClear()
  206.  
  207.     -- Confirm settings with the user, then save to file
  208.     CabinScreen = ECAPI.addPrintLine(CabinScreen,"No settings file found. Confirming settings.")
  209.  
  210.     -- To ensure this code plays nice with multiple elevators, Unique network names are required (as best as can)
  211.     CabinScreen, CabinConfig = ECAPI.getConfigFromUser(CabinScreen,CabinConfig,"Network")
  212.     CabinScreen = ECAPI.printConfig(CabinConfig,CabinScreen,"Network")
  213.    
  214.     -- Confirm modem side
  215.     CabinScreen, CabinConfig = ECAPI.getConfigFromUser(CabinScreen,CabinConfig,"Modem")
  216.     CabinScreen = ECAPI.printConfig(CabinConfig,CabinScreen,"Modem")
  217.  
  218.     -- Confirm Welcome message
  219.     CabinScreen, CabinConfig = ECAPI.getConfigFromUser(CabinScreen,CabinConfig,"Intro")
  220.     CabinScreen = ECAPI.printConfig(CabinConfig,CabinScreen,"Intro")
  221.     -- Confirm First column heading
  222.     CabinScreen, CabinConfig = ECAPI.getConfigFromUser(CabinScreen,CabinConfig,"Floor")
  223.     CabinScreen = ECAPI.printConfig(CabinConfig,CabinScreen,"Floor")
  224.     -- Confirm Second column heading
  225.     CabinScreen, CabinConfig = ECAPI.getConfigFromUser(CabinScreen,CabinConfig,"Description")
  226.     CabinScreen = ECAPI.printConfig(CabinConfig,CabinScreen,"Description")
  227.  
  228.        
  229.     -- Write to file
  230.     ECAPI.table_save(CabinConfig,cabinSettingsFile)
  231.     termClear()
  232. end
  233.  
  234. local function startupConfirmation()
  235.     -- Check if there's a settings file
  236.     if fs.exists(cabinSettingsFile) then
  237.         termClear()
  238.         CabinConfig = ECAPI.table_load(cabinSettingsFile)
  239.         ECAPI.verifyConfig(DefaultConfig,CabinConfig)
  240.         termClear()
  241.         CabinScreen = ECAPI.justPrintLine(CabinScreen,"Settings loaded.")
  242.         os.sleep(0.5)
  243.     else
  244.         createNewSettings()
  245.     end
  246.     ECAPI.openModem(modemSide())
  247.     if (ECAPI.getConfigOption(CabinConfig,"AccessPW") ~= "") then
  248.         Unlocked = false
  249.     end
  250.     local badSide = ECAPI.getConfigOption(CabinConfig,"Invalid")
  251.     if (badSide ~= "") then
  252.         redstone.setOutput(badSide,true)
  253.     end
  254. end
  255.  
  256.  
  257. -- ######################################################
  258. -- ##  Input Actions                                   ##
  259. -- ######################################################
  260.  
  261. -- MAX Topic details: 45 characters per table entry
  262. --                      |---------------------------------------------|
  263. local helpTopics = {
  264.     ["reboot"]      = { "Restart this terminal." ,},
  265.     ["clear"]       = { "Refresh the terminal screen." ,},
  266.     ["config"]      = { "Prints the current settings. Will not print",
  267.                         "any set passwords." ,},
  268.     ["reconfig"]    = { "With no parameters, re-run the whole setup.",
  269.                         "RECONFIG [option] to change a single setting",
  270.                         "Note: Reconfig can be password protected via",
  271.                         "the ConfigPW setting. If this password is",
  272.                         "lost, you will need server admin help or be",
  273.                         "forced to recreate the terminal." ,},
  274.     ["broadcast"]   = { "Manually broadcast <message>",},
  275.     ["send"]        = { "Manually send <id> <message>",},
  276.  
  277.     ["floors"]      = { "Print the usual cabin display"},
  278. }
  279.  
  280. local function printHelp(topic)
  281.     justPrintLine("Help on '"..string.upper(topic).."':")
  282.     local t = helpTopics[topic]
  283.     for _, text in ipairs(t) do
  284.         justPrintLine("  "..text)
  285.     end
  286. end
  287.  
  288. local commands = {
  289.     ["help"] = function (x)
  290.             if (x[1] ~= nil) then
  291.                 printHelp(x[1])
  292.             else
  293.                 justPrintLine("Please use HELP [COMMAND]. ? for Command List")
  294.             end
  295.         end,
  296.     ["reboot"] = function (x) os.reboot() end,
  297.     ["clear"] = function (x) termClear() end,
  298.     ["broadcast"] = function (x)
  299.             CabinScreen = justPrintInfo(CabinScreen,"REDNET",nil,nil,"Broadcast: "..table.concat(x," ",2))
  300.             ECAPI.broadcast(networkName(),table.concat(x," "))
  301.         end,
  302.     ["send"] = function (x)
  303.             CabinScreen = justPrintInfo(CabinScreen,"REDNET",nil,nil,"Send("..tonumber(x[1]).."): "..table.concat(x," ",2))
  304.             ECAPI.send(networkName(),tonumber(x[1]),table.concat(x," ",2))
  305.         end,
  306.    
  307.     ["config"] = function (x)
  308.             justPrintLine("Current Configuration:")
  309.             justPrintLine("-------------------------------")
  310.             ECAPI.printConfig(CabinConfig,CabinScreen)
  311.         end,
  312.     ["reconfig"] = function (x) reconfig(x) end,
  313.  
  314.     ["floors"] = function (x) printFloors() end,
  315.  
  316. }
  317.  
  318. local function printCommands()
  319.     local col = 1
  320.     local row = {}
  321.     for named, _ in pairs(commands) do
  322.         if (col < 5) then row[col] = string.upper(named) end
  323.         col = col + 1
  324.         if (col == 5) then
  325.             justPrintLine(ECAPI.padLeft(row[1],12," ")..ECAPI.padLeft(row[2],12," ")..ECAPI.padLeft(row[3],12," ")..ECAPI.padLeft(row[4],11," "))
  326.             row = {}
  327.             col = 1
  328.         end
  329.     end
  330.     if (col > 1) then
  331.         -- handles 'remainders'
  332.         justPrintLine(ECAPI.padLeft(row[1],12," ")..ECAPI.padLeft(row[2],12," ")..ECAPI.padLeft(row[3],12," ")..ECAPI.padLeft(row[4],11," "))
  333.     end
  334. end
  335.  
  336.  
  337. local function processCommands(input)
  338.     local arg = ECAPI.explode(" ",input)
  339.     local command = arg[1]
  340.     table.remove(arg,1)
  341.     if Unlocked then
  342.         if ECAPI.tableContainsKey(commands, command) then
  343.             commands[command](arg)
  344.         else
  345.             --validate the floor is in the list
  346.             if ECAPI.tableContainsKey(floorDescs,tonumber(command)) then
  347.                 if ECAPI.tableContainsKey(floorPass,tonumber(command)) then
  348.                     -- that floor is secure(ish)
  349.                     -- ask for the password
  350.                     local pwinput = ECAPI.getPasswordInput("Password:")
  351.                    
  352.                     -- check if it's right
  353.                     if (pwinput == ECAPI.decrypt(floorPass[tonumber(command)], networkName())) then
  354.                         changeUpdate(""..command.." selected.")
  355.                         selectFloor(command)
  356.                     else
  357.                         local badSide = ECAPI.getConfigOption(CabinConfig,"Invalid")
  358.                         if (badSide == "") then
  359.                             changeUpdate("Wrong Password!")
  360.                         else
  361.                             changeUpdate("Wrong password.  Goodbye.")
  362.                             os.sleep(0.2)
  363.                             redstone.setOutput(badSide,false)
  364.                             os.sleep(60)
  365.                             redstone.setOutput(badSide,true)
  366.                         end
  367.                     end
  368.                 else
  369.                     changeUpdate(""..command.." selected.")
  370.                     selectFloor(command)
  371.                 end
  372.             else
  373.                 changeUpdate("Invalid selection.")
  374.             end
  375.         end
  376.     else
  377.         if ECAPI.checkPassword(CabinScreen,CabinConfig,"AccessPW") then
  378.             Unlocked = true
  379.             printFloors()
  380.         end
  381.     end
  382. end
  383.  
  384.  
  385. -- ######################################################
  386. -- ##  Handler Functions                               ##
  387. -- ######################################################
  388.  
  389. -- User input listener
  390. local function userConsole()
  391.     while KeepWaiting do
  392.         if Unlocked then
  393.             processCommands(ECAPI.getInput("Command:"))
  394.         else
  395.             if ECAPI.checkPassword(CabinScreen,CabinConfig,"AccessPW") then
  396.                 Unlocked = true
  397.                 relockAlarm = os.setAlarm(os.time()+2)
  398.                 printFloors()
  399.             else
  400.                 local badSide = ECAPI.getConfigOption(CabinConfig,"Invalid")
  401.                 if (badSide == "") then
  402.                     changeUpdate("Invalid password.")
  403.                 else
  404.                     changeUpdate("Wrong password.  Goodbye.")
  405.                     os.sleep(0.2)
  406.                     redstone.setOutput(badSide,false)
  407.                     os.sleep(60)
  408.                     redstone.setOutput(badSide,true)
  409.                 end
  410.             end
  411.         end
  412.     end
  413. end
  414.  
  415. -- Rednet listener
  416. local function rednetListener()
  417.     while KeepWaiting do       
  418.         local sendID, rawmessage, distance = rednet.receive()
  419.         local packet = ECAPI.explode("|",rawmessage)
  420.         --print("MSG ["..sendID.."]: "..table.concat(packet,"|",2))
  421.         --os.sleep(3)
  422.         if packet[1] == networkName() then
  423.             if string.lower(packet[2]) ==     'floordata'       then
  424.                 printFloors(packet[3])
  425.             elseif string.lower(packet[2]) == 'reboot'          then
  426.                 os.reboot()
  427.             elseif string.lower(packet[2]) == 'displayfloor'           then
  428.                 justPrintLine('displayfloor: '..packet[3])
  429.                 updateFloor(tonumber(packet[3]),">>")
  430.                 --print("arrival")
  431.                 --os.sleep(1)  
  432.             elseif string.lower(packet[2]) == 'arrival'           then 
  433.                 updateFloor(tonumber(packet[3]),">>")
  434.             elseif string.lower(packet[2]) == 'displayup'           then
  435.                 --justPrintLine('displayup: '..packet[4])
  436.                 updateFloor(tonumber(packet[4]),packet[3])
  437.             elseif string.lower(packet[2]) == 'displaydown'           then
  438.                 --justPrintLine('displaydown: '..packet[4])
  439.                 updateFloor(tonumber(packet[4]),packet[3])
  440.             end
  441.         end
  442.     end
  443. end
  444.  
  445. local function relocker()
  446.     while KeepWaiting do
  447.         local evt,p1 = os.pullEvent("alarm")
  448.         if (relockAlarm ~= nil) and (p1 == relockAlarm) then
  449.             Unlocked = false
  450.             relockAlarm = nil
  451.         end
  452.     end
  453. end
  454.  
  455. -- ######################################################
  456. -- ##  Actual Run Program                              ##
  457. -- ######################################################
  458.  
  459. startupConfirmation()
  460. justPrintLine('Gathering floor information.')
  461. --os.sleep(4) -- startup delay to the network boot up
  462. -- get floors from network
  463. ECAPI.broadcast(networkName(),'getfloors')
  464. parallel.waitForAll(userConsole,rednetListener,relocker)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement