Advertisement
Guest User

setup

a guest
Feb 26th, 2015
175
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 14.11 KB | None | 0 0
  1. --[[
  2. Elevator Control Setup by Hamish Robertson
  3. Aliases: OminousPenguin, MC username: Peren
  4.  
  5. Thanks to Jonnathon Clayton for identifying a replacement for Rednet Cables (Project Red)
  6.  
  7. Licence: Creative Commons Attribution-NonCommercial-ShareAlike (http://creativecommons.org/licenses/by-nc-sa/3.0/)
  8.  
  9. This is a LUA program for ComputerCraft, a Minecraft mod by Daniel Ratcliffe aka dan200 (http://www.computercraft.info/)
  10. This program is for controlling elevators from the Railcraft mod (http://www.railcraft.info/)
  11. For help and feedback please use this forum thread: http://www.computercraft.info/forums2/index.php?/topic/1302-railcraft-mod-elevator-control/
  12.  
  13. You are permitted to modify and or build upon this work.
  14. If you make your own version publicly available, then please also publish it at the above forum thread. Thank you and happy coding!
  15.  
  16. NOTE: This is the setup program. It will create a file called elevator.cfg and download the main program to elevator-main.lua
  17.  
  18. Use Ctrl+T to terminate the program
  19. --]]
  20.  
  21. CHANNEL_ELEVATOR = 34080
  22.  
  23. function writeToPos(x, y, str)
  24.     term.setCursorPos(x, y)
  25.     term.write(str)
  26. end
  27. function clearArea(x1,y1,x2,y2)
  28.     for i=y1,y2 do
  29.         writeToPos(x1,i,string.rep(" ",x2-x1))
  30.     end
  31. end
  32. function eventHandle(tHandlers, f, ...)
  33.     f = tHandlers[f]
  34.     if type(f) == "function" then return f(...) end
  35. end
  36. function debug(msg)
  37.     print(msg)
  38.     os.pullEvent("key")
  39. end
  40. function printSetupHeader(saving, title)
  41.     term.clear()
  42.     writeToPos(32,1,"Hold Ctrl+T to exit")
  43.     title = title or "Setup"
  44.     eqs = ("="):rep((46 - title:len())/2).."  "
  45.     writeToPos(2,2,eqs..title..eqs:reverse())
  46.     if saving then writeToPos(5,5,"Saving data... "); term.setCursorBlink(true) end
  47. end
  48.  
  49. function getModemSide()
  50.     -- Find all attached modems
  51.     local sides = {"left","right","top","bottom","back","front"}
  52.     local i = 1
  53.     while i <= #sides do
  54.         if peripheral.getType(sides[i]) ~= "modem" then
  55.             table.remove(sides,i)
  56.         else
  57.             i = i + 1
  58.         end
  59.     end
  60.  
  61.     if #sides == 0 then
  62.         return nil
  63.     elseif #sides == 1 then
  64.         return sides[1]
  65.     end
  66.  
  67.     -- If there is more than one modem attached, ask user to choose one
  68.     local selected = 1
  69.     local function redraw()
  70.         printSetupHeader()
  71.         writeToPos(7,9,"Use the modem on the          side")
  72.         for i=1,#sides do
  73.             if (i == selected) then
  74.                 writeToPos(29,9,sides[i])
  75.             else
  76.                 if (9-selected+i)<9 then
  77.                     term.setCursorPos(29,(8-selected+i))
  78.                 else
  79.                     term.setCursorPos(29,(10-selected+i))
  80.                 end
  81.                 term.write(sides[i])
  82.             end
  83.         end--for
  84.         writeToPos(4,18,"[ Arrow keys to select, Enter to confirm ]")
  85.     end--redraw()
  86.  
  87.     redraw(); -- First draw
  88.  
  89.     while true do
  90.         local _, keycode = os.pullEvent ("key")
  91.         if (keycode == 200) then -- up
  92.             if selected > 1 then selected = selected-1 end
  93.         elseif (keycode == 208) then -- down
  94.             if selected < 6 then selected = selected+1 end
  95.         elseif (keycode == 28) then -- enter
  96.             return sides[selected]
  97.         end
  98.         redraw()
  99.     end
  100. end--getModemSide()
  101.  
  102. function getElevatorID()
  103.     local elevatorID
  104.     printSetupHeader()
  105.     writeToPos(3, 4, "Are you using the Bundled Connector")
  106.     writeToPos(6, 6, "from the Extra Peripherals mod? [Y/n] ")
  107.     bundledConnector = string.lower(string.sub(io.read(),1,1))
  108.     if (bundledConnector=='y') then
  109.         bundledConnector = 'bundledConnector:yes'
  110.     else
  111.         bundledConnector = 'bundledConnector:no'
  112.     end
  113.     printSetupHeader()
  114.     writeToPos(3, 4, "Searching for other elevator shafts.")
  115.     writeToPos(3, 6, "(Remember that rain reduces modem range)")
  116.     writeToPos(5, 10, "This may take a few seconds...")
  117.     local modem = peripheral.wrap(modemSide)
  118.     modem.open(os.getComputerID())
  119.     modem.transmit(CHANNEL_ELEVATOR, os.getComputerID(), "ELEV\030ALL\030DISCOVER") -- Ask all elevator terminals in range to tell us their elevator ID
  120.     local tElevatorIDs = {}
  121.     local mt = {
  122.         tMeta = {},
  123.         iIndex = 1,
  124.         __newindex = function(t,k,v)
  125.             this = getmetatable(t)
  126.             if this.tMeta[k] ~= true then
  127.                 this.tMeta[k] = true
  128.                 rawset(t,this.iIndex,k)
  129.                 this.iIndex = this.iIndex + 1
  130.             end
  131.         end,
  132.     }
  133.     setmetatable(tElevatorIDs,mt)
  134.     local _, _, sChannel, sReplyChannel, sMessage
  135.     local discoveryTimer
  136.     local tHandlers = {
  137.         modem_message = function (_, sChannel, sReplyChannel, sMessage, nDistance)
  138.             discoveryTimer = os.startTimer(3) -- Reset timer
  139.             local iter = string.gmatch(sMessage, "([^\030]+)")
  140.             if sChannel == os.getComputerID() and iter() == "ELEV" then
  141.                 local eID = iter()
  142.                 if iter() == "ID" then
  143.                     tElevatorIDs[eID] = true
  144.                 end
  145.             end
  146.         end,
  147.         timer = function (timerID)
  148.             if timerID == discoveryTimer then   return true end
  149.         end
  150.     }
  151.     discoveryTimer = os.startTimer(3) -- Loop will timeout after three seconds of not receiving an event
  152.     while true do
  153.         local v = eventHandle(tHandlers, os.pullEvent())
  154.         if v then break end
  155.     end
  156.  
  157.     local function getCustomID()
  158.         writeToPos(5, 7, "Please specify a shaft ID: ")
  159.         writeToPos(2, 9, "IDs can have letters, numbers and other characters")
  160.         writeToPos(2, 11, "Note that this is an identifier for the whole")
  161.         writeToPos(2, 12, "elevator shaft, not just this floor.")
  162.         writeToPos(2, 14, "Eg. The elevator shaft with ID 'House1' might have")
  163.         writeToPos(2, 15, "3 floors: 'Entrance', 'Workshop' and 'Mine'")
  164.         term.setCursorPos(32, 7); term.setCursorBlink(true)
  165.         return io.read()
  166.     end
  167.  
  168.     printSetupHeader(false,"READ ME")
  169.     if #tElevatorIDs < 2 then
  170.         writeToPos(2, 4, "Note the difference between elevators and floors.")
  171.         writeToPos(2, 5, "An elevator shaft has multiple floors.")
  172.         writeToPos(2, 6, "You can have multiple separate elevator shafts.")
  173.         writeToPos(2, 8, "Because they communicate wirelessly, one shaft")
  174.         writeToPos(2, 9, "might overhear another nearby shaft.")
  175.         writeToPos(2, 11, "To prevent interference you must tell each floor")
  176.         writeToPos(2, 12, "which elevator shaft it is part of.")
  177.         writeToPos(2, 14, "Eg. The elevator shaft with ID 'House1' might have")
  178.         writeToPos(2, 15, "3 floors: 'Entrance', 'Workshop' and 'Mine'")
  179.         writeToPos(6, 17, "Press any key to continue...")
  180.         os.pullEvent("key")
  181.     end
  182.     printSetupHeader()
  183.     if #tElevatorIDs == 0 then
  184.         writeToPos(2, 5, "No nearby elevator shafts detected")
  185.         elevatorID = getCustomID()
  186.     else
  187.         writeToPos(2, 5, "The following elevator shafts were detected:")
  188.         writeToPos(3, 18, "Enter: Add this floor to the selected shaft")
  189.         writeToPos(3, 19, "Tab: Start a new elevator shaft")
  190.         local selected = 1
  191.         for k,v in ipairs(tElevatorIDs) do
  192.             writeToPos(5, 6+k, v)
  193.         end
  194.         writeToPos(3,7,">")
  195.         local function updateSelection(previousSelection)
  196.             writeToPos(3,6+previousSelection," ")
  197.             writeToPos(3,6+selected,">")
  198.         end
  199.         while true do
  200.             previousSelection = selected
  201.             local _, keycode = os.pullEvent ("key")
  202.             if (keycode == 200) then -- up
  203.                 if selected > 1 then selected = selected-1 end
  204.             elseif (keycode == 208) then -- down
  205.                 previousSelection = selected
  206.                 if selected < #tElevatorIDs then selected = selected+1 end
  207.             elseif (keycode == 28) then -- enter
  208.                 elevatorID = tElevatorIDs[selected]
  209.                 break
  210.             elseif (keycode == 15) then -- tab
  211.                 printSetupHeader()
  212.                 writeToPos(2, 5, "You have chosen to create a new elevator shaft")
  213.                 elevatorID = getCustomID()
  214.                 break
  215.             end
  216.             updateSelection(previousSelection)
  217.         end
  218.     end
  219.     return elevatorID
  220. end--getElevatorID()
  221.  
  222. function getFloorName()
  223.     printSetupHeader()
  224.     writeToPos(7,9,"Enter a name/label for this floor: ")
  225.     term.setCursorPos(14,11); term.setCursorBlink(true)
  226.     local name
  227.     repeat
  228.         name = io.read()
  229.     until name ~= ""
  230.     return name
  231. end--getFloorName()
  232.  
  233. function getGPS()
  234.     printSetupHeader()
  235.     writeToPos(5, 5, "Waiting for GPS response... ")
  236.     term.setCursorPos(5,7)
  237.     local x, y, z = gps.locate(2)
  238.     if x ~= nil then
  239.         term.write("... coordinates received")
  240.         writeToPos(5, 9, "Start GPS host in the background?")
  241.         local _, keycode, selected = nil, nil, 1
  242.         writeToPos(14,11,"[ Yes ]             No")
  243.         while true do
  244.             term.setCursorPos(14,11)
  245.             _, keycode = os.pullEvent ("key")
  246.             if (keycode == 205) or (keycode == 49) then -- right
  247.                 if selected == 1 then
  248.                     selected = 2
  249.                     term.write("  Yes             [ No ]")
  250.                 end
  251.             elseif (keycode == 203) or (keys.getName(keycode) == n) then -- left
  252.                 if selected == 2 then
  253.                     selected = 1
  254.                     term.write("[ Yes ]             No  ")
  255.                 end
  256.             elseif (keycode == 28) then -- enter
  257.                 if selected == 1 then
  258.                     return x,y,z
  259.                 else
  260.                     return nil, y
  261.                 end
  262.             end
  263.         end--while
  264.     else -- We didn't get coords from GPS
  265.         term.write("... could not determine coordinates")
  266.         return
  267.     end
  268. end--getGPS()
  269.  
  270. function getCoordsInput()
  271.     printSetupHeader()
  272.     writeToPos(8,7,"x coordinate:")
  273.     writeToPos(8,8,"y coordinate:")
  274.     writeToPos(8,9,"z coordinate:")
  275.     writeToPos(4,13,"Important: If your GPS hosts are all in a")
  276.     writeToPos(4,14,"vertical line (same x & y coordinates), then")
  277.     writeToPos(4,15,"you need to place another host off to the side")
  278.     writeToPos(4,16,"to enable an accurate GPS fix")
  279.     writeToPos(4,17,"(Usage: gps host x y z")
  280.     term.setCursorPos(22,7); term.setCursorBlink(true)
  281.    
  282.     local selected, inputs = 1, {"","",""}
  283.    
  284.     local function redraw()
  285.         term.setCursorPos(22+inputs[selected]:len(),6+selected)
  286.     end
  287.    
  288.     local eventHandlers = {
  289.         key = function(keycode)
  290.             if (keycode == 200) and (selected > 1) then -- up
  291.                 selected = selected-1
  292.                 redraw(selected);
  293.             elseif (selected < 3) and ((keycode == 208) or (keycode == 28)) then -- down
  294.                 selected = selected+1
  295.                 redraw(selected);
  296.             elseif (keycode == 28) then -- enter
  297.                 for i,input in ipairs(inputs) do
  298.                     if inputs[selected] == "" then return end
  299.                 end
  300.                 return inputs[1], inputs[2], inputs[3]
  301.             elseif (keycode == 14) and inputs[selected] ~= "" then -- backspace
  302.                     inputs[selected] = inputs[selected]:sub(1,-2)
  303.                     term.setCursorPos(22+inputs[selected]:len(),6+selected)
  304.                     term.write(" ")
  305.                     term.setCursorPos(22+inputs[selected]:len(),6+selected)
  306.             end
  307.         end,
  308.  
  309.         char = function(c)
  310.             if (inputs[selected]:len() < 6) and (string.find(c, "[%d\-]") ~= nil) then -- number entered
  311.                 inputs[selected] = inputs[selected]..c
  312.                 term.write(c)
  313.             end
  314.         end,
  315.  
  316.         handle = function (self, f, ...)
  317.             f = self[f]
  318.             if type(f) == "function" then return f(...) end
  319.         end
  320.     }
  321.     while true do
  322.         local x,y,z = eventHandlers:handle(os.pullEvent())
  323.         if x then return x,y,z end
  324.     end
  325. end--getCoordsInput
  326.  
  327. function getFloorCoords()
  328.     -- We need at least the y (height) coordinate so we can know what order the floors are in
  329.     printSetupHeader()
  330.     writeToPos(4,4,"The y (height) coordinate is required so that")
  331.     writeToPos(4,5,"floors can be listed in the correct order.")
  332.     writeToPos(4,7,"You have a few options:")
  333.     writeToPos(6,10,"1. Enter y coordinate:")
  334.     writeToPos(6,12,"2. Use GPS (requires 4 GPS hosts)")
  335.     writeToPos(6,14,"3. Enter x,y,z and then this computer")
  336.     writeToPos(13,15,"can become a GPS host.")
  337.     writeToPos(7,16,"(recommended if you have over 4 floors)")
  338.     writeToPos(2,19,"(Press F3 to view player coordinates)")
  339.    
  340.     local selected, line, y = 1, {10,12,14}, ""
  341.  
  342.     local function redraw(i, clear)
  343.         term.setCursorPos(3,8+(2*i))
  344.         local t = (clear and write(" ")) or write("[")
  345.         term.setCursorPos(49,8+(2*i))
  346.         local t = clear and write(" ") or write("]")
  347.         term.setCursorPos(29,10)
  348.     end
  349.  
  350.     redraw(1)
  351.     term.setCursorBlink(true)
  352.  
  353.     local eventHandlers = {
  354.         key = function(keycode)
  355.             if (keycode == 200) then -- up
  356.                 if selected > 1 then
  357.                     redraw(selected, true)
  358.                     selected = selected-1
  359.                     if selected == 1 then term.setCursorBlink(true) end
  360.                     redraw(selected);
  361.                 end
  362.             elseif (keycode == 208) then -- down
  363.                 if selected < 3 then
  364.                     redraw(selected, true)
  365.                     selected = selected+1
  366.                     term.setCursorBlink(false)
  367.                     redraw(selected);
  368.                 end
  369.             elseif (keycode == 28) then -- enter
  370.                 if ((selected == 1) and (y ~= "")) then
  371.                     return true, nil, y
  372.                 elseif selected == 2 then
  373.                     return true, getGPS()
  374.                 elseif selected == 3 then
  375.                     return true, getCoordsInput() -- input all 3
  376.                 end
  377.             elseif (keycode == 14) then -- backspace
  378.                 if ((selected == 1) and (y ~= "")) then
  379.                     y = y:sub(1,-2)
  380.                     term.setCursorPos(29+y:len(),10)
  381.                     term.write(" ")
  382.                     term.setCursorPos(29+y:len(),10)
  383.                 end
  384.             end
  385.         end,
  386.  
  387.         char = function(c)
  388.             if (selected == 1) and ((y:len() < 6) and (string.find(c, "[%d\-]") ~= nil)) then -- number entered
  389.                 y = y..c
  390.                 term.setCursorPos(28+y:len(),10)
  391.                 term.write(c)
  392.             end
  393.         end,
  394.  
  395.         handle = function (self, f, ...)
  396.             f = self[f]
  397.             if type(f) == "function" then return f(...) end
  398.         end
  399.     }
  400.     while true do
  401.         local RETURN,x,y,z = eventHandlers:handle(os.pullEvent())
  402.         if RETURN then return x,y,z end
  403.     end
  404. end--getFloorCoords()
  405.  
  406. fs.delete("elevator-main.lua")
  407. if not shell.run("pastebin", "get", "iJWyUQVr", "elevator-main.lua") then
  408.     print("Failed to download main program. Try manually from pastebin: iJWyUQVr\n(this is just the setup component)")
  409.     return
  410. end
  411.  
  412. modemSide = getModemSide()
  413. if modemSide == nil then
  414.     printSetupHeader()
  415.     writeToPos(15,6,"! No modem detected !")
  416.     writeToPos(8,9,"A modem is required for")
  417.     writeToPos(8,11,"communication with the other floors")
  418.     writeToPos(4,13,"Please attach a modem then try again")
  419.     return -- terminate program
  420. end
  421.  
  422. local elevatorID = getElevatorID()
  423.  
  424. local floorName = getFloorName()
  425.  
  426. local x,y,z
  427.  
  428. while true do
  429.     x,y,z = getFloorCoords()
  430.     if y==nil then
  431.         writeToPos(5, 11, "Press any key to continue...")
  432.         os.pullEvent("key")
  433.     else
  434.         break
  435.     end
  436. end
  437. local coords = y
  438. if x and y then
  439.     coords = x.."\31"..y.."\31"..z
  440. end
  441.  
  442. printSetupHeader(true)
  443. configPath = shell.resolve(".").."/elevator.cfg"
  444. fs.delete(configPath)
  445. local file = io.open(configPath, "w")
  446. file:write(bundledConnector.."\n")
  447. file:write(modemSide.."\n")
  448. file:write(elevatorID.."\n")
  449. file:write(coords.."\n")
  450. file:write(y.."\31"..floorName)
  451. file:close()
  452. term.write("Done")
  453.  
  454. writeToPos(5,7,"Setting elevator-main.lua to run on startup... ")
  455.  
  456. file = io.open("/startup", "w")
  457. file:write("shell.run(\"/"..shell.resolve(".").."/elevator-main.lua\")")
  458. file:close()
  459. term.write("Done")
  460.  
  461. writeToPos(5, 9, "Press any key to reboot...")
  462. os.pullEvent("key")
  463. os.reboot()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement