Advertisement
kd8lvt

Repost for my convenience!

Jun 28th, 2015
656
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 12.29 KB | None | 0 0
  1. --THIS IS A REPOST OF:
  2. -- OpenPeripheral terminal glasses demo
  3. -- by boq
  4. --original file can be found here: http://goo.gl/n5HPN8
  5.  
  6. local p = peripheral.wrap("back")
  7.  
  8. if p == nil then
  9.     print("Peripheral not found")
  10.     return
  11. end
  12.  
  13. p.clear()
  14.  
  15. -- helper function and constants
  16. function pack(...)
  17.     return {...}
  18. end
  19.  
  20. FORMAT_CHAR = "\194\167"
  21. FORMAT_BOLD = FORMAT_CHAR .. 'l'
  22.  
  23. -- NOTE
  24. -- this program works with multiple users (i.e. multiple players attached to same terminal) so it may be more complicated then single user variant
  25. -- if it's not needed, programs may as well operate only on global surface
  26. local players = {}
  27.  
  28. local attachedCount = 0
  29. local capturedCount = 0
  30.  
  31. -- initialize global display surface
  32. local labelPlayers = p.addText(-1, 0, "Player count: 0/0");
  33. labelPlayers.setScreenAnchor("right", "top") -- screen origin (0,0) for this object will be in top right corner
  34. labelPlayers.setObjectAnchor("right", "bottom") -- "center" of object will be on bottom right corner
  35. labelPlayers.setRotation(-90) -- object will be rotated by 90 degrees counter-clockwise around object anchor (bottom right corner)
  36.  
  37. local function initializePlayer(name, uuid)
  38.     local playerData = { name = name, uuid = uuid}
  39.  
  40.     -- now we can use private surface, visible only to owner player
  41.     playerData.surface = p.getSurfaceByUUID(playerData.uuid)
  42.     labelPlayer = playerData.surface.addText(0, 0, "Hello " .. playerData.name)
  43.     labelPlayer.setAlignment("middle","top") -- identical as 'labelPlayer.setScreenAnchor("middle","top") labelPlayer.setObjectAnchor("middle","top")'
  44.  
  45.     -- Minecraft color codes are interpreted (http://minecraft.gamepedia.com/Formatting_codes) - but since Lua does not support Unicode, you need to use "\194\167" instead of "\x00A7"
  46.     playerData.labelWaiting = playerData.surface.addText(0, 0, FORMAT_BOLD .. "CAPTURE MODE: OFF", 0xFF0000)
  47.     playerData.labelWaiting.setAlignment("right", "bottom")
  48.  
  49.     -- add to global list
  50.     -- general hint: it's always safer to use UUID instead of names!
  51.     players[playerData.uuid] = playerData
  52. end
  53.  
  54. local function changeCounter(deltaAttached, deltaCaptured)
  55.     attachedCount = attachedCount + deltaAttached
  56.     capturedCount = capturedCount + deltaCaptured
  57.     labelPlayers.setText("Player count: " .. attachedCount .. "/" .. capturedCount)
  58. end
  59.  
  60. -- initialize already attached players
  61. for _, user in pairs(p.getUsers()) do
  62.     initializePlayer(user.name, user.uuid)
  63.     changeCounter(1, 0)
  64. end
  65.  
  66. local timerCallbacks = {}
  67.  
  68. p.sync() -- this operation is needed to make changes visible to player
  69. -- classic event loop
  70. while true do
  71.     evt = pack(os.pullEvent())
  72.     -- full list of glasses events: https://gist.github.com/boq/9a098b89ee102cbf1b2b
  73.     print(evt[1])
  74.     --  easy break condition - it's just ComputerCraft event
  75.     if evt[1] == "key" then
  76.         break -- exit loop
  77.     -- player started wearing glasses
  78.     elseif evt[1] == "glasses_attach" then
  79.         local name = evt[3]
  80.         local uuid = evt[4]
  81.         initializePlayer(name, uuid)
  82.         changeCounter(1, 0)
  83.     -- player logged out or took off glasses
  84.     elseif evt[1] == "glasses_detach" then
  85.         -- components on private surface are automatically cleared when player removes glasses
  86.         local playerUuid = evt[4]
  87.         players[playerUuid] = nil
  88.         changeCounter(-1,0)
  89.     -- player used wireless keyboard - computer will now start getting keyboard and mouse events
  90.     elseif evt[1] == "glasses_capture" then
  91.         changeCounter(0, 1)
  92.         local playerUuid = evt[4]
  93.         local playerData = players[playerUuid]
  94.  
  95.         if playerData then
  96.             local surface = playerData.surface
  97.             playerData.labelWaiting.setText(FORMAT_BOLD .. "CAPTURE MODE: ON")
  98.             playerData.labelWaiting.setColor(0x00FF00)
  99.  
  100.             -- middle boxes - will be used as bottons and to present click position
  101.             local function createBox(color)
  102.                 local box = surface.addBox(0,0, 25, 25, color)
  103.                 box.setScreenAnchor("middle","middle")
  104.                 box.setUserdata(color) -- userdata is variable that can be used to store anything (no type or content restrictions, except for functions). It's also not synchronized to clients
  105.                 return box
  106.             end
  107.  
  108.             createBox(0xFF0000).setObjectAnchor("left", "top")
  109.             createBox(0x00FF00).setObjectAnchor("right", "top")
  110.             createBox(0x0000FF).setObjectAnchor("right", "bottom")
  111.             createBox(0xFFFFFF).setObjectAnchor("left", "bottom")
  112.  
  113.             -- horizontal progress bar
  114.             surface.addBox(0,20, 100, 5, 0x000000).setAlignment("middle","top")
  115.  
  116.             -- vertical progress bar
  117.             surface.addBox(0,0, 5, 100, 0x000000).setAlignment("right","middle")
  118.  
  119.             playerData.horizontalMarker = surface.addBox(0, 20, 5, 5, 0xFFFFFF)
  120.             playerData.horizontalMarker.setAlignment("middle","top")
  121.  
  122.             playerData.verticalMarker = surface.addBox(0, 0, 5, 5, 0xFFFFFF)
  123.             playerData.verticalMarker.setAlignment("right","middle")
  124.  
  125.             -- pseudo-console stuff
  126.             playerData.textInput = surface.addText(0,0,">", 0x00FF00)
  127.             playerData.textInput.setScreenAnchor("left", "middle")
  128.             playerData.textInput.setObjectAnchor("left", "bottom")
  129.  
  130.             playerData.textOutput = surface.addText(0,0,"", 0x0000FF)
  131.             playerData.textOutput.setScreenAnchor("left", "middle")
  132.             playerData.textOutput.setObjectAnchor("left", "top")
  133.             playerData.textOutput.setVisible(false)
  134.  
  135.             -- mouse button indicator
  136.             surface.addBox(10, 10, 19, 9, 0xAAAAAA).setObjectAnchor("middle","top") -- button indicator background
  137.  
  138.             playerData.mouseButtons = {}
  139.  
  140.             local function createMouseButton(deltaX)
  141.                 local button = surface.addBox(10 + deltaX, 12, 5, 5, 0xFF0000)
  142.                 button.setZ(5) -- move it over box (default Z == 0)
  143.                 button.setVisible(false)
  144.                 button.setObjectAnchor("middle","top")
  145.                 return button
  146.             end
  147.  
  148.             -- mouse and keyboard codes are same as LWJGL, see http://minecraft.gamepedia.com/Key_codes
  149.  
  150.             playerData.mouseButtons[0] = createMouseButton(-5) -- left button
  151.             playerData.mouseButtons[1] = createMouseButton(5) -- right button
  152.             playerData.mouseButtons[2] = createMouseButton(0) -- middle button
  153.         end
  154.     -- player exited from keyboard GUI
  155.     elseif evt[1] == "glasses_release" then
  156.         changeCounter(0, -1)
  157.         local playerUuid = evt[4]
  158.         local playerData = players[playerUuid]
  159.  
  160.         if playerData then
  161.             -- recreate display to initial state
  162.             playerData.surface.clear()
  163.             initializePlayer(playerData.name, playerData.uuid)
  164.         end
  165.     -- player pressed mouse button anywhere in GUI
  166.     elseif evt[1] == "glasses_mouse_down" then
  167.         local playerUuid = evt[4]
  168.         local playerData = players[playerUuid]
  169.  
  170.         if playerData then
  171.             local buttonId = evt[5]
  172.             -- changing visibility is faster than recreating and removing element every time
  173.             local button = playerData.mouseButtons[buttonId]
  174.             if button then
  175.                 button.setVisible(true)
  176.             end
  177.         end
  178.     -- player released mouse button anywhere in GUI
  179.     elseif evt[1] == "glasses_mouse_up" then
  180.         local playerUuid = evt[4]
  181.         local playerData = players[playerUuid]
  182.  
  183.         local buttonId = evt[5]
  184.  
  185.         if playerData then
  186.             button = playerData.mouseButtons[buttonId]
  187.             if button then
  188.                 button.setVisible(false)
  189.             end
  190.         end
  191.  
  192.     -- player clicked on component (if you got this event, then you won't get glasses_mouse_down. Same for glasses_component_mouse_up and glasses_mouse_up)
  193.     elseif evt[1] == "glasses_component_mouse_down" then
  194.         local isPrivate = evt[6]
  195.         if isPrivate then
  196.             local playerUuid = evt[4]
  197.             local playerData = players[playerUuid]
  198.  
  199.             if playerData then
  200.                 local objectId = evt[5]
  201.                 local component = playerData.surface.getObjectById(objectId)
  202.                 local userdata = component.getUserdata()
  203.                 if userdata then -- only rectangles in middle have that value filled
  204.                     -- capture control is special object used to control few properties of keyboard GUI
  205.                     local capture = p.getCaptureControl(playerUuid)
  206.                     capture.setBackground(userdata)
  207.                     playerData.horizontalMarker.setColor(userdata)
  208.                     playerData.verticalMarker.setColor(userdata)
  209.                 end
  210.  
  211.                 -- click position is given in pixels from top left component corner
  212.                 local clickX = evt[7]
  213.                 local clickY = evt[8]
  214.  
  215.                 -- -0.5, since anchor is in middle of screen
  216.                 playerData.horizontalMarker.setX((clickX / 25.0 - 0.5) * 100)
  217.                 playerData.verticalMarker.setY((clickY / 25.0 - 0.5) * 100)
  218.             end
  219.         end
  220.     elseif evt[1] == "glasses_key_down" then
  221.         local playerUuid = evt[4]
  222.         local playerData = players[playerUuid]
  223.  
  224.         if playerData then
  225.             local code = evt[5] -- control code, see http://minecraft.gamepedia.com/Key_codes for keymap
  226.             local char = evt[6] -- may be 0 for some control characters
  227.  
  228.             local input = playerData.textInput
  229.             local contents = input.getText()
  230.             if code == 14 then -- backspace
  231.                 if contents:len() > 1 then
  232.                     input.setText(contents:sub(0, -2))
  233.                 end
  234.             elseif code == 28 then -- enter
  235.                 input.setText(">")
  236.  
  237.                 local function setOutput(text, color)
  238.                     playerData.textOutput.setText(text)
  239.                     playerData.textOutput.setColor(color)
  240.                     playerData.textOutput.setVisible(true)
  241.                     local timerId = os.startTimer(1)
  242.                     timerCallbacks[timerId] = function ()
  243.                         playerData.textOutput.setVisible(false)
  244.                     end
  245.                 end
  246.  
  247.                 -- alternative to writing tons of ifs. Normally would be initialized once before main loop, but this is demo/semi-tutorial
  248.                 local commands = {}
  249.  
  250.                 function commands.hello(playerData)
  251.                     setOutput("Hi!", 0xFFFF00)
  252.                 end
  253.  
  254.                 function commands.exit(playerData)
  255.                     -- manually exit keyboard GUI. Player can do it itself by using escape button (same as normal Minecraft GUIs)
  256.                     p.getCaptureControl(playerData.uuid).stopCapturing()
  257.                 end
  258.  
  259.                 -- sorry, couldn't resist
  260.                 local function createColorCommand(color)
  261.                     return function(playerData)
  262.                         playerData.textInput.setColor(color)
  263.                         setOutput("OK", color)
  264.                     end
  265.                 end
  266.  
  267.                 commands.red = createColorCommand(0xFF0000)
  268.                 commands.green = createColorCommand(0x00FF00)
  269.                 commands.blue = createColorCommand(0x0000FF)
  270.  
  271.                 command = contents:sub(2, -1)
  272.                 commandSub = commands[command] -- skip console prompt
  273.  
  274.                 if commandSub then
  275.                     commandSub(playerData)
  276.                 else
  277.                     setOutput("invalid command: " .. command, 0xFF0000)
  278.                 end
  279.  
  280.             elseif string.byte(char) >= 0x20 then -- skip unprintable control chars
  281.                 input.setText(contents .. char)
  282.             end
  283.         end
  284.     elseif evt[1] == "timer" then
  285.         local timerId = evt[2]
  286.         callback = timerCallbacks[timerId]
  287.         if callback then callback() end
  288.         timerCallbacks[timerId] = nil
  289.     end
  290.  
  291.     -- sync() shouldn't be called often
  292.     -- if called without changes, nothing will happen
  293.     -- this method is synchronized - i.e. it can be executed only once per game tick (1/20 s). Other instructions don't have that limit
  294.     p.sync()
  295. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement