Advertisement
Guest User

Untitled

a guest
Nov 21st, 2017
64
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 38.63 KB | None | 0 0
  1. tArgs = {...}
  2.  
  3. if OneOS then
  4. --running under OneOS
  5. OneOS.ToolBarColour = colours.white
  6. OneOS.ToolBarTextColour = colours.grey
  7. end
  8.  
  9. local _w, _h = term.getSize()
  10.  
  11. local round = function(num, idp)
  12. local mult = 10^(idp or 0)
  13. return math.floor(num * mult + 0.5) / mult
  14. end
  15.  
  16. InterfaceElements = {}
  17.  
  18. Drawing = {
  19.  
  20. Screen = {
  21. Width = _w,
  22. Height = _h
  23. },
  24.  
  25. DrawCharacters = function (x, y, characters, textColour,bgColour)
  26. Drawing.WriteStringToBuffer(x, y, characters, textColour, bgColour)
  27. end,
  28.  
  29. DrawBlankArea = function (x, y, w, h, colour)
  30. Drawing.DrawArea (x, y, w, h, " ", 1, colour)
  31. end,
  32.  
  33. DrawArea = function (x, y, w, h, character, textColour, bgColour)
  34. --width must be greater than 1, other wise we get a stack overflow
  35. if w < 0 then
  36. w = w * -1
  37. elseif w == 0 then
  38. w = 1
  39. end
  40.  
  41. for ix = 1, w do
  42. local currX = x + ix - 1
  43. for iy = 1, h do
  44. local currY = y + iy - 1
  45. Drawing.WriteToBuffer(currX, currY, character, textColour, bgColour)
  46. end
  47. end
  48. end,
  49.  
  50. DrawImage = function(_x,_y,tImage, w, h)
  51. if tImage then
  52. for y = 1, h do
  53. if not tImage[y] then
  54. break
  55. end
  56. for x = 1, w do
  57. if not tImage[y][x] then
  58. break
  59. end
  60. local bgColour = tImage[y][x]
  61. local textColour = tImage.textcol[y][x] or colours.white
  62. local char = tImage.text[y][x]
  63. Drawing.WriteToBuffer(x+_x-1, y+_y-1, char, textColour, bgColour)
  64. end
  65. end
  66. elseif w and h then
  67. Drawing.DrawBlankArea(x, y, w, h, colours.green)
  68. end
  69. end,
  70. --using .nft
  71. LoadImage = function(path)
  72. local image = {
  73. text = {},
  74. textcol = {}
  75. }
  76. local fs = fs
  77. if OneOS then
  78. fs = OneOS.FS
  79. end
  80. if fs.exists(path) then
  81. local _open = io.open
  82. if OneOS then
  83. _open = OneOS.IO.open
  84. end
  85. local file = _open(path, "r")
  86. local sLine = file:read()
  87. local num = 1
  88. while sLine do
  89. table.insert(image, num, {})
  90. table.insert(image.text, num, {})
  91. table.insert(image.textcol, num, {})
  92.  
  93. --As we're no longer 1-1, we keep track of what index to write to
  94. local writeIndex = 1
  95. --Tells us if we've hit a 30 or 31 (BG and FG respectively)- next char specifies the curr colour
  96. local bgNext, fgNext = false, false
  97. --The current background and foreground colours
  98. local currBG, currFG = nil,nil
  99. for i=1,#sLine do
  100. local nextChar = string.sub(sLine, i, i)
  101. if nextChar:byte() == 30 then
  102. bgNext = true
  103. elseif nextChar:byte() == 31 then
  104. fgNext = true
  105. elseif bgNext then
  106. currBG = Drawing.GetColour(nextChar)
  107. bgNext = false
  108. elseif fgNext then
  109. currFG = Drawing.GetColour(nextChar)
  110. fgNext = false
  111. else
  112. if nextChar ~= " " and currFG == nil then
  113. currFG = colours.white
  114. end
  115. image[num][writeIndex] = currBG
  116. image.textcol[num][writeIndex] = currFG
  117. image.text[num][writeIndex] = nextChar
  118. writeIndex = writeIndex + 1
  119. end
  120. end
  121. num = num+1
  122. sLine = file:read()
  123. end
  124. file:close()
  125. end
  126. return image
  127. end,
  128.  
  129. DrawCharactersCenter = function(x, y, w, h, characters, textColour,bgColour)
  130. w = w or Drawing.Screen.Width
  131. h = h or Drawing.Screen.Height
  132. x = x or 0
  133. y = y or 0
  134. x = math.ceil((w - #characters) / 2) + x
  135. y = math.floor(h / 2) + y
  136.  
  137. Drawing.DrawCharacters(x, y, characters, textColour, bgColour)
  138. end,
  139.  
  140. GetColour = function(hex)
  141. if hex == ' ' then
  142. return colours.transparent
  143. end
  144. local value = tonumber(hex, 16)
  145. if not value then return nil end
  146. value = math.pow(2,value)
  147. return value
  148. end,
  149.  
  150. Clear = function (_colour)
  151. _colour = _colour or colours.black
  152. Drawing.ClearBuffer()
  153. Drawing.DrawBlankArea(1, 1, Drawing.Screen.Width, Drawing.Screen.Height, _colour)
  154. end,
  155.  
  156. Buffer = {},
  157. BackBuffer = {},
  158.  
  159. DrawBuffer = function()
  160. for y,row in pairs(Drawing.Buffer) do
  161. for x,pixel in pairs(row) do
  162. local shouldDraw = true
  163. local hasBackBuffer = true
  164. if Drawing.BackBuffer[y] == nil or Drawing.BackBuffer[y][x] == nil or #Drawing.BackBuffer[y][x] ~= 3 then
  165. hasBackBuffer = false
  166. end
  167. if hasBackBuffer and Drawing.BackBuffer[y][x][1] == Drawing.Buffer[y][x][1] and Drawing.BackBuffer[y][x][2] == Drawing.Buffer[y][x][2] and Drawing.BackBuffer[y][x][3] == Drawing.Buffer[y][x][3] then
  168. shouldDraw = false
  169. end
  170. if shouldDraw then
  171. term.setBackgroundColour(pixel[3])
  172. term.setTextColour(pixel[2])
  173. term.setCursorPos(x, y)
  174. term.write(pixel[1])
  175. end
  176. end
  177. end
  178. Drawing.BackBuffer = Drawing.Buffer
  179. Drawing.Buffer = {}
  180. term.setCursorPos(1,1)
  181. end,
  182.  
  183. ClearBuffer = function()
  184. Drawing.Buffer = {}
  185. end,
  186.  
  187. WriteStringToBuffer = function (x, y, characters, textColour,bgColour)
  188. for i = 1, #characters do
  189. local character = characters:sub(i,i)
  190. Drawing.WriteToBuffer(x + i - 1, y, character, textColour, bgColour)
  191. end
  192. end,
  193.  
  194. WriteToBuffer = function(x, y, character, textColour,bgColour)
  195. x = round(x)
  196. y = round(y)
  197. if bgColour == colours.transparent then
  198. Drawing.Buffer[y] = Drawing.Buffer[y] or {}
  199. Drawing.Buffer[y][x] = Drawing.Buffer[y][x] or {"", colours.white, colours.black}
  200. Drawing.Buffer[y][x][1] = character
  201. Drawing.Buffer[y][x][2] = textColour
  202. else
  203. Drawing.Buffer[y] = Drawing.Buffer[y] or {}
  204. Drawing.Buffer[y][x] = {character, textColour, bgColour}
  205. end
  206. end,
  207. }
  208.  
  209. Current = {
  210. Document = nil,
  211. TextInput = nil,
  212. CursorPos = {1,1},
  213. CursorColour = colours.black,
  214. Selection = {8, 36},
  215. Window = nil,
  216. HeaderText = '',
  217. StatusText = '',
  218. StatusColour = colours.grey,
  219. StatusScreen = true,
  220. ButtonOne = nil,
  221. ButtonTwo = nil,
  222. Locked = false,
  223. Page = '',
  224. PageControls = {}
  225. }
  226.  
  227. isRunning = true
  228.  
  229. Events = {}
  230.  
  231. Button = {
  232. X = 1,
  233. Y = 1,
  234. Width = 0,
  235. Height = 0,
  236. BackgroundColour = colours.lightGrey,
  237. TextColour = colours.white,
  238. ActiveBackgroundColour = colours.lightGrey,
  239. Text = "",
  240. Parent = nil,
  241. _Click = nil,
  242. Toggle = nil,
  243.  
  244. AbsolutePosition = function(self)
  245. return self.Parent:AbsolutePosition()
  246. end,
  247.  
  248. Draw = function(self)
  249. local bg = self.BackgroundColour
  250. local tc = self.TextColour
  251. if type(bg) == 'function' then
  252. bg = bg()
  253. end
  254.  
  255. if self.Toggle then
  256. tc = colours.white
  257. bg = self.ActiveBackgroundColour
  258. end
  259.  
  260. local pos = GetAbsolutePosition(self)
  261. Drawing.DrawBlankArea(pos.X, pos.Y, self.Width, self.Height, bg)
  262. Drawing.DrawCharactersCenter(pos.X, pos.Y, self.Width, self.Height, self.Text, tc, bg)
  263. end,
  264.  
  265. Initialise = function(self, x, y, width, height, backgroundColour, parent, click, text, textColour, toggle, activeBackgroundColour)
  266. local new = {} -- the new instance
  267. setmetatable( new, {__index = self} )
  268. height = height or 1
  269. new.Width = width or #text + 2
  270. new.Height = height
  271. new.Y = y
  272. new.X = x
  273. new.Text = text or ""
  274. new.BackgroundColour = backgroundColour or colours.lightGrey
  275. new.TextColour = textColour or colours.white
  276. new.ActiveBackgroundColour = activeBackgroundColour or colours.lightBlue
  277. new.Parent = parent
  278. new._Click = click
  279. new.Toggle = toggle
  280. return new
  281. end,
  282.  
  283. Click = function(self, side, x, y)
  284. if self._Click then
  285. if self:_Click(side, x, y, not self.Toggle) ~= false and self.Toggle ~= nil then
  286. self.Toggle = not self.Toggle
  287. Draw()
  288. end
  289. return true
  290. else
  291. return false
  292. end
  293. end
  294. }
  295.  
  296. Label = {
  297. X = 1,
  298. Y = 1,
  299. Width = 0,
  300. Height = 0,
  301. BackgroundColour = colours.lightGrey,
  302. TextColour = colours.white,
  303. Text = "",
  304. Parent = nil,
  305.  
  306. AbsolutePosition = function(self)
  307. return self.Parent:AbsolutePosition()
  308. end,
  309.  
  310. Draw = function(self)
  311. local bg = self.BackgroundColour
  312. local tc = self.TextColour
  313.  
  314. if self.Toggle then
  315. tc = UIColours.MenuBarActive
  316. bg = self.ActiveBackgroundColour
  317. end
  318.  
  319. local pos = GetAbsolutePosition(self)
  320. Drawing.DrawCharacters(pos.X, pos.Y, self.Text, self.TextColour, self.BackgroundColour)
  321. end,
  322.  
  323. Initialise = function(self, x, y, text, textColour, backgroundColour, parent)
  324. local new = {} -- the new instance
  325. setmetatable( new, {__index = self} )
  326. height = height or 1
  327. new.Width = width or #text + 2
  328. new.Height = height
  329. new.Y = y
  330. new.X = x
  331. new.Text = text or ""
  332. new.BackgroundColour = backgroundColour or colours.white
  333. new.TextColour = textColour or colours.black
  334. new.Parent = parent
  335. return new
  336. end,
  337.  
  338. Click = function(self, side, x, y)
  339. return false
  340. end
  341. }
  342.  
  343. TextBox = {
  344. X = 1,
  345. Y = 1,
  346. Width = 0,
  347. Height = 0,
  348. BackgroundColour = colours.lightGrey,
  349. TextColour = colours.black,
  350. Parent = nil,
  351. TextInput = nil,
  352. Placeholder = '',
  353.  
  354. AbsolutePosition = function(self)
  355. return self.Parent:AbsolutePosition()
  356. end,
  357.  
  358. Draw = function(self)
  359. local pos = GetAbsolutePosition(self)
  360. Drawing.DrawBlankArea(pos.X, pos.Y, self.Width, self.Height, self.BackgroundColour)
  361. local text = self.TextInput.Value
  362. if #tostring(text) > (self.Width - 2) then
  363. text = text:sub(#text-(self.Width - 3))
  364. if Current.TextInput == self.TextInput then
  365. Current.CursorPos = {pos.X + 1 + self.Width-2, pos.Y}
  366. end
  367. else
  368. if Current.TextInput == self.TextInput then
  369. Current.CursorPos = {pos.X + 1 + self.TextInput.CursorPos, pos.Y}
  370. end
  371. end
  372.  
  373. if #tostring(text) == 0 then
  374. Drawing.DrawCharacters(pos.X + 1, pos.Y, self.Placeholder, colours.lightGrey, self.BackgroundColour)
  375. else
  376. Drawing.DrawCharacters(pos.X + 1, pos.Y, text, self.TextColour, self.BackgroundColour)
  377. end
  378.  
  379. term.setCursorBlink(true)
  380.  
  381. Current.CursorColour = self.TextColour
  382. end,
  383.  
  384. Initialise = function(self, x, y, width, height, parent, text, backgroundColour, textColour, done, numerical)
  385. local new = {} -- the new instance
  386. setmetatable( new, {__index = self} )
  387. height = height or 1
  388. new.Width = width or #text + 2
  389. new.Height = height
  390. new.Y = y
  391. new.X = x
  392. new.TextInput = TextInput:Initialise(text or '', function(key)
  393. if done then
  394. done(key)
  395. end
  396. Draw()
  397. end, numerical)
  398. new.BackgroundColour = backgroundColour or colours.lightGrey
  399. new.TextColour = textColour or colours.black
  400. new.Parent = parent
  401. return new
  402. end,
  403.  
  404. Click = function(self, side, x, y)
  405. Current.Input = self.TextInput
  406. self:Draw()
  407. end
  408. }
  409.  
  410. TextInput = {
  411. Value = "",
  412. Change = nil,
  413. CursorPos = nil,
  414. Numerical = false,
  415. IsDocument = nil,
  416.  
  417. Initialise = function(self, value, change, numerical, isDocument)
  418. local new = {} -- the new instance
  419. setmetatable( new, {__index = self} )
  420. new.Value = tostring(value)
  421. new.Change = change
  422. new.CursorPos = #tostring(value)
  423. new.Numerical = numerical
  424. new.IsDocument = isDocument or false
  425. return new
  426. end,
  427.  
  428. Insert = function(self, str)
  429. if self.Numerical then
  430. str = tostring(tonumber(str))
  431. end
  432.  
  433. local selection = OrderSelection()
  434.  
  435. if self.IsDocument and selection then
  436. self.Value = string.sub(self.Value, 1, selection[1]-1) .. str .. string.sub( self.Value, selection[2]+2)
  437. self.CursorPos = selection[1]
  438. Current.Selection = nil
  439. else
  440. local _, newLineAdjust = string.gsub(self.Value:sub(1, self.CursorPos), '\n','')
  441.  
  442. self.Value = string.sub(self.Value, 1, self.CursorPos + newLineAdjust) .. str .. string.sub( self.Value, self.CursorPos + 1 + newLineAdjust)
  443. self.CursorPos = self.CursorPos + 1
  444. end
  445.  
  446. self.Change(key)
  447. end,
  448.  
  449. Extract = function(self, remove)
  450. local selection = OrderSelection()
  451. if self.IsDocument and selection then
  452. local _, newLineAdjust = string.gsub(self.Value:sub(selection[1], selection[2]), '\n','')
  453. local str = string.sub(self.Value, selection[1], selection[2]+1+newLineAdjust)
  454. if remove then
  455. self.Value = string.sub(self.Value, 1, selection[1]-1) .. string.sub( self.Value, selection[2]+2+newLineAdjust)
  456. self.CursorPos = selection[1] - 1
  457. Current.Selection = nil
  458. end
  459. return str
  460. end
  461. end,
  462.  
  463. Char = function(self, char)
  464. if char == 'nil' then
  465. return
  466. end
  467. self:Insert(char)
  468. end,
  469.  
  470. Key = function(self, key)
  471. if key == keys.enter then
  472. if self.IsDocument then
  473. self.Value = string.sub(self.Value, 1, self.CursorPos ) .. '\n' .. string.sub( self.Value, self.CursorPos + 1 )
  474. self.CursorPos = self.CursorPos + 1
  475. end
  476. self.Change(key)
  477. elseif key == keys.left then
  478. -- Left
  479. if self.CursorPos > 0 then
  480. local colShift = FindColours(string.sub( self.Value, self.CursorPos, self.CursorPos))
  481. self.CursorPos = self.CursorPos - 1 - colShift
  482. self.Change(key)
  483. end
  484.  
  485. elseif key == keys.right then
  486. -- Right
  487. if self.CursorPos < string.len(self.Value) then
  488. local colShift = FindColours(string.sub( self.Value, self.CursorPos+1, self.CursorPos+1))
  489. self.CursorPos = self.CursorPos + 1 + colShift
  490. self.Change(key)
  491. end
  492.  
  493. elseif key == keys.backspace then
  494. -- Backspace
  495. if self.IsDocument and Current.Selection then
  496. self:Extract(true)
  497. self.Change(key)
  498. elseif self.CursorPos > 0 then
  499. local colShift = FindColours(string.sub( self.Value, self.CursorPos, self.CursorPos))
  500. local _, newLineAdjust = string.gsub(self.Value:sub(1, self.CursorPos), '\n','')
  501.  
  502. self.Value = string.sub( self.Value, 1, self.CursorPos - 1 - colShift + newLineAdjust) .. string.sub( self.Value, self.CursorPos + 1 - colShift + newLineAdjust)
  503. self.CursorPos = self.CursorPos - 1 - colShift
  504. self.Change(key)
  505. end
  506. elseif key == keys.home then
  507. -- Home
  508. self.CursorPos = 0
  509. self.Change(key)
  510. elseif key == keys.delete then
  511. if self.IsDocument and Current.Selection then
  512. self:Extract(true)
  513. self.Change(key)
  514. elseif self.CursorPos < string.len(self.Value) then
  515. self.Value = string.sub( self.Value, 1, self.CursorPos ) .. string.sub( self.Value, self.CursorPos + 2 )
  516. self.Change(key)
  517. end
  518. elseif key == keys["end"] then
  519. -- End
  520. self.CursorPos = string.len(self.Value)
  521. self.Change(key)
  522. elseif key == keys.up and self.IsDocument then
  523. -- Up
  524. if Current.Document.CursorPos then
  525. local page = Current.Document.Pages[Current.Document.CursorPos.Page]
  526. self.CursorPos = page:GetCursorPosFromPoint(Current.Document.CursorPos.Collum + page.MarginX, Current.Document.CursorPos.Line - page.MarginY - 1 + Current.Document.ScrollBar.Scroll, true)
  527. self.Change(key)
  528. end
  529. elseif key == keys.down and self.IsDocument then
  530. -- Down
  531. if Current.Document.CursorPos then
  532. local page = Current.Document.Pages[Current.Document.CursorPos.Page]
  533. self.CursorPos = page:GetCursorPosFromPoint(Current.Document.CursorPos.Collum + page.MarginX, Current.Document.CursorPos.Line - page.MarginY + 1 + Current.Document.ScrollBar.Scroll, true)
  534. self.Change(key)
  535. end
  536. end
  537. end
  538. }
  539.  
  540. local Capitalise = function(str)
  541. return str:sub(1, 1):upper() .. str:sub(2, -1)
  542. end
  543.  
  544.  
  545. local getNames = peripheral.getNames or function()
  546. local tResults = {}
  547. for n,sSide in ipairs( rs.getSides() ) do
  548. if peripheral.isPresent( sSide ) then
  549. table.insert( tResults, sSide )
  550. local isWireless = false
  551. if not pcall(function()isWireless = peripheral.call(sSide, 'isWireless') end) then
  552. isWireless = true
  553. end
  554. if peripheral.getType( sSide ) == "modem" and not isWireless then
  555. local tRemote = peripheral.call( sSide, "getNamesRemote" )
  556. for n,sName in ipairs( tRemote ) do
  557. table.insert( tResults, sName )
  558. end
  559. end
  560. end
  561. end
  562. return tResults
  563. end
  564.  
  565. Peripheral = {
  566. GetPeripheral = function(_type)
  567. for i, p in ipairs(Peripheral.GetPeripherals()) do
  568. if p.Type == _type then
  569. return p
  570. end
  571. end
  572. end,
  573.  
  574. Call = function(type, ...)
  575. local tArgs = {...}
  576. local p = Peripheral.GetPeripheral(type)
  577. peripheral.call(p.Side, unpack(tArgs))
  578. end,
  579.  
  580. GetPeripherals = function(filterType)
  581. local peripherals = {}
  582. for i, side in ipairs(getNames()) do
  583. local name = peripheral.getType(side):gsub("^%l", string.upper)
  584. local code = string.upper(side:sub(1,1))
  585. if side:find('_') then
  586. code = side:sub(side:find('_')+1)
  587. end
  588.  
  589. local dupe = false
  590. for i, v in ipairs(peripherals) do
  591. if v[1] == name .. ' ' .. code then
  592. dupe = true
  593. end
  594. end
  595.  
  596. if not dupe then
  597. local _type = peripheral.getType(side)
  598. local isWireless = false
  599. if _type == 'modem' then
  600. if not pcall(function()isWireless = peripheral.call(sSide, 'isWireless') end) then
  601. isWireless = true
  602. end
  603. if isWireless then
  604. _type = 'wireless_modem'
  605. name = 'W '..name
  606. end
  607. end
  608. if not filterType or _type == filterType then
  609. table.insert(peripherals, {Name = name:sub(1,8) .. ' '..code, Fullname = name .. ' ('..side:sub(1, 1):upper() .. side:sub(2, -1)..')', Side = side, Type = _type, Wireless = isWireless})
  610. end
  611. end
  612. end
  613. return peripherals
  614. end,
  615.  
  616. PresentNamed = function(name)
  617. return peripheral.isPresent(name)
  618. end,
  619.  
  620. CallType = function(type, ...)
  621. local tArgs = {...}
  622. local p = Peripheral.GetPeripheral(type)
  623. return peripheral.call(p.Side, unpack(tArgs))
  624. end,
  625.  
  626. CallNamed = function(name, ...)
  627. local tArgs = {...}
  628. return peripheral.call(name, unpack(tArgs))
  629. end
  630. }
  631.  
  632. Wireless = {
  633. Channels = {
  634. UltimateDoorlockPing = 4210,
  635. UltimateDoorlockRequest = 4211,
  636. UltimateDoorlockRequestReply = 4212,
  637. },
  638.  
  639. isOpen = function(channel)
  640. return Peripheral.CallType('wireless_modem', 'isOpen', channel)
  641. end,
  642.  
  643. Open = function(channel)
  644. if not Wireless.isOpen(channel) then
  645. Peripheral.CallType('wireless_modem', 'open', channel)
  646. end
  647. end,
  648.  
  649. close = function(channel)
  650. Peripheral.CallType('wireless_modem', 'close', channel)
  651. end,
  652.  
  653. closeAll = function()
  654. Peripheral.CallType('wireless_modem', 'closeAll')
  655. end,
  656.  
  657. transmit = function(channel, replyChannel, message)
  658. Peripheral.CallType('wireless_modem', 'transmit', channel, replyChannel, textutils.serialize(message))
  659. end,
  660.  
  661. Present = function()
  662. if Peripheral.GetPeripheral('wireless_modem') == nil then
  663. return false
  664. else
  665. return true
  666. end
  667. end,
  668.  
  669. FormatMessage = function(message, messageID, destinationID)
  670. return {
  671. content = textutils.serialize(message),
  672. senderID = os.getComputerID(),
  673. senderName = os.getComputerLabel(),
  674. channel = channel,
  675. replyChannel = reply,
  676. messageID = messageID or math.random(10000),
  677. destinationID = destinationID
  678. }
  679. end,
  680.  
  681. Timeout = function(func, time)
  682. time = time or 1
  683. parallel.waitForAny(func, function()
  684. sleep(time)
  685. --log('Timeout!'..time)
  686. end)
  687. end,
  688.  
  689. RecieveMessage = function(_channel, messageID, timeout)
  690. open(_channel)
  691. local done = false
  692. local event, side, channel, replyChannel, message = nil
  693. Timeout(function()
  694. while not done do
  695. event, side, channel, replyChannel, message = os.pullEvent('modem_message')
  696. if channel ~= _channel then
  697. event, side, channel, replyChannel, message = nil
  698. else
  699. message = textutils.unserialize(message)
  700. message.content = textutils.unserialize(message.content)
  701. if messageID and messageID ~= message.messageID or (message.destinationID ~= nil and message.destinationID ~= os.getComputerID()) then
  702. event, side, channel, replyChannel, message = nil
  703. else
  704. done = true
  705. end
  706. end
  707. end
  708. end,
  709. timeout)
  710. return event, side, channel, replyChannel, message
  711. end,
  712.  
  713. Initialise = function()
  714. if Wireless.Present() then
  715. for i, c in pairs(Wireless.Channels) do
  716. Wireless.Open(c)
  717. end
  718. end
  719. end,
  720.  
  721. HandleMessage = function(event, side, channel, replyChannel, message, distance)
  722. message = textutils.unserialize(message)
  723. message.content = textutils.unserialize(message.content)
  724.  
  725. if channel == Wireless.Channels.Ping then
  726. if message.content == 'Ping!' then
  727. SendMessage(replyChannel, 'Pong!', nil, message.messageID)
  728. end
  729. elseif message.destinationID ~= nil and message.destinationID ~= os.getComputerID() then
  730. elseif Wireless.Responder then
  731. Wireless.Responder(event, side, channel, replyChannel, message, distance)
  732. end
  733. end,
  734.  
  735. SendMessage = function(channel, message, reply, messageID, destinationID)
  736. reply = reply or channel + 1
  737. Wireless.Open(channel)
  738. Wireless.Open(reply)
  739. local _message = Wireless.FormatMessage(message, messageID, destinationID)
  740. Wireless.transmit(channel, reply, _message)
  741. return _message
  742. end,
  743.  
  744. Ping = function()
  745. local message = SendMessage(Channels.Ping, 'Ping!', Channels.PingReply)
  746. RecieveMessage(Channels.PingReply, message.messageID)
  747. end
  748. }
  749.  
  750. function GetAbsolutePosition(object)
  751. local obj = object
  752. local i = 0
  753. local x = 1
  754. local y = 1
  755. while true do
  756. x = x + obj.X - 1
  757. y = y + obj.Y - 1
  758.  
  759. if not obj.Parent then
  760. return {X = x, Y = y}
  761. end
  762.  
  763. obj = obj.Parent
  764.  
  765. if i > 32 then
  766. return {X = 1, Y = 1}
  767. end
  768.  
  769. i = i + 1
  770. end
  771.  
  772. end
  773.  
  774. function Draw()
  775. Drawing.Clear(colours.white)
  776.  
  777. if Current.StatusScreen then
  778. Drawing.DrawCharactersCenter(1, -2, nil, nil, Current.HeaderText, colours.blue, colours.white)
  779. Drawing.DrawCharactersCenter(1, -1, nil, nil, 'by oeed', colours.lightGrey, colours.white)
  780. Drawing.DrawCharactersCenter(1, 1, nil, nil, Current.StatusText, Current.StatusColour, colours.white)
  781. end
  782.  
  783. if Current.ButtonOne then
  784. Current.ButtonOne:Draw()
  785. end
  786.  
  787. if Current.ButtonTwo then
  788. Current.ButtonTwo:Draw()
  789. end
  790.  
  791. for i, v in ipairs(Current.PageControls) do
  792. v:Draw()
  793. end
  794.  
  795. Drawing.DrawBuffer()
  796.  
  797. if Current.TextInput and Current.CursorPos and not Current.Menu and not(Current.Window and Current.Document and Current.TextInput == Current.Document.TextInput) and Current.CursorPos[2] > 1 then
  798. term.setCursorPos(Current.CursorPos[1], Current.CursorPos[2])
  799. term.setCursorBlink(true)
  800. term.setTextColour(Current.CursorColour)
  801. else
  802. term.setCursorBlink(false)
  803. end
  804. end
  805. MainDraw = Draw
  806.  
  807. function GenerateFingerprint()
  808. local str = ""
  809. for _ = 1, 256 do
  810. local char = math.random(32, 126)
  811. --if char == 96 then char = math.random(32, 95) end
  812. str = str .. string.char(char)
  813. end
  814. return str
  815. end
  816.  
  817. function MakeFingerprint()
  818. local h = fs.open('.fingerprint', 'w')
  819. if h then
  820. h.write(GenerateFingerprint())
  821. end
  822. h.close()
  823. Current.Fingerprint = str
  824. end
  825.  
  826. local drawTimer = nil
  827. function SetText(header, status, colour, isReset)
  828. if header then
  829. Current.HeaderText = header
  830. end
  831. if status then
  832. Current.StatusText = status
  833. end
  834. if colour then
  835. Current.StatusColour = colour
  836. end
  837. Draw()
  838. if not isReset then
  839. statusResetTimer = os.startTimer(2)
  840. end
  841. end
  842.  
  843. function ResetStatus()
  844. if pocket then
  845. if Current.Locked then
  846. SetText('Ultimate Door Lock', 'Add Wireless Modem to PDA', colours.red, true)
  847. else
  848. SetText('Ultimate Door Lock', 'Ready', colours.grey, true)
  849. end
  850. else
  851. if Current.Locked then
  852. SetText('Ultimate Door Lock', ' Attach a Wireless Modem then reboot', colours.red, true)
  853. else
  854. SetText('Ultimate Door Lock', 'Ready', colours.grey, true)
  855. end
  856. end
  857. end
  858.  
  859. function ResetPage()
  860. Wireless.Responder = function()end
  861. pingTimer = nil
  862. Current.PageControls = nil
  863. Current.StatusScreen = false
  864. Current.ButtonOne = nil
  865. Current.ButtonTwo = nil
  866. Current.PageControls = {}
  867. CloseDoor()
  868. end
  869.  
  870. function PocketInitialise()
  871. Current.ButtonOne = Button:Initialise(Drawing.Screen.Width - 6, Drawing.Screen.Height - 1, nil, nil, nil, nil, Quit, 'Quit', colours.black)
  872. if not Wireless.Present() then
  873. Current.Locked = true
  874. ResetStatus()
  875. return
  876. end
  877. Wireless.Initialise()
  878. ResetStatus()
  879. if fs.exists('.fingerprint') then
  880. local h = fs.open('.fingerprint', 'r')
  881. if h then
  882. Current.Fingerprint = h.readAll()
  883. else
  884. MakeFingerprint()
  885. end
  886. h.close()
  887. else
  888. MakeFingerprint()
  889. end
  890.  
  891. Wireless.Responder = function(event, side, channel, replyChannel, message, distance)
  892. if channel == Wireless.Channels.UltimateDoorlockPing then
  893. Wireless.SendMessage(Wireless.Channels.UltimateDoorlockRequest, Current.Fingerprint, Wireless.Channels.UltimateDoorlockRequestReply, nil, message.senderID)
  894. elseif channel == Wireless.Channels.UltimateDoorlockRequestReply then
  895. if message.content == true then
  896. SetText(nil, 'Opening Door', colours.green)
  897. else
  898. SetText(nil, ' Access Denied', colours.red)
  899. end
  900. end
  901. end
  902. end
  903.  
  904. function FingerprintIsOnWhitelist(fingerprint)
  905. if Current.Settings.Whitelist then
  906. for i, f in ipairs(Current.Settings.Whitelist) do
  907. if f == fingerprint then
  908. return true
  909. end
  910. end
  911. end
  912. return false
  913. end
  914.  
  915. function SaveSettings()
  916. Current.Settings = Current.Settings or {}
  917. local h = fs.open('.settings', 'w')
  918. if h then
  919. h.write(textutils.serialize(Current.Settings))
  920. end
  921. h.close()
  922. end
  923.  
  924. local closeDoorTimer = nil
  925. function OpenDoor()
  926. if Current.Settings and Current.Settings.RedstoneSide then
  927. SetText(nil, 'Opening Door', colours.green)
  928. redstone.setOutput(Current.Settings.RedstoneSide, true)
  929. closeDoorTimer = os.startTimer(0.6)
  930. end
  931. end
  932.  
  933. function CloseDoor()
  934. if Current.Settings and Current.Settings.RedstoneSide then
  935. if redstone.getOutput(Current.Settings.RedstoneSide) then
  936. SetText(nil, 'Closing Door', colours.orange)
  937. redstone.setOutput(Current.Settings.RedstoneSide, false)
  938. sleep(5)
  939. redstone.setOutput(Current.Settings.RedstoneSide, true)
  940. sleep(5)
  941. redstone.setOutput(Current.Settings.RedstoneSide, false)
  942. os.reboot()
  943. end
  944. end
  945. end
  946.  
  947. DefaultSettings = {
  948. Whitelist = {},
  949. RedstoneSide = 'back',
  950. Distance = 10
  951. }
  952.  
  953. function RegisterPDA(event, drive)
  954. if disk.hasData(drive) then
  955. local _fs = fs
  956. if OneOS then
  957. _fs = OneOS.FS
  958. end
  959. local path = disk.getMountPath(drive)
  960. local addStartup = true
  961. if _fs.exists(path..'/System/') then
  962. path = path..'/System/'
  963. addStartup = false
  964. end
  965. local fingerprint = nil
  966. if _fs.exists(path..'/.fingerprint') then
  967. local h = _fs.open(path..'/.fingerprint', 'r')
  968. if h then
  969. local str = h.readAll()
  970. if #str == 256 then
  971. fingerprint = str
  972. end
  973. end
  974. h.close()
  975. end
  976. if not fingerprint then
  977. fingerprint = GenerateFingerprint()
  978. local h = _fs.open(path..'/.fingerprint', 'w')
  979. h.write(fingerprint)
  980. h.close()
  981. if addStartup then
  982. local h = fs.open(shell.getRunningProgram(), 'r')
  983. local startup = h.readAll()
  984. h.close()
  985. local h = _fs.open(path..'/startup', 'w')
  986. h.write(startup)
  987. h.close()
  988. end
  989. end
  990. if not FingerprintIsOnWhitelist(fingerprint) then
  991. table.insert(Current.Settings.Whitelist, fingerprint)
  992. SaveSettings()
  993. end
  994. disk.eject(drive)
  995. SetText(nil, 'Registered Pocket Computer', colours.green)
  996. end
  997. end
  998.  
  999. function HostSetup()
  1000. ResetPage()
  1001. Current.Page = 'HostSetup'
  1002. Current.ButtonTwo = Button:Initialise(Drawing.Screen.Width - 6, Drawing.Screen.Height - 1, nil, nil, nil, nil, HostStatusPage, 'Save', colours.black)
  1003. if not Current.Settings then
  1004. Current.Settings = DefaultSettings
  1005. end
  1006.  
  1007. local sideButtons = {}
  1008. local function resetSideToggle(self)
  1009. for i, v in ipairs(sideButtons) do
  1010. if v.Toggle ~= nil then
  1011. v.Toggle = false
  1012. end
  1013. end
  1014. Current.Settings.RedstoneSide = self.Text:lower()
  1015. SaveSettings()
  1016. end
  1017.  
  1018. table.insert(Current.PageControls, Label:Initialise(2, 2, 'Redstone Side'))
  1019. sideButtons = {
  1020. Button:Initialise(2, 4, nil, nil, nil, nil, resetSideToggle, 'Back', colours.black, false, colours.green),
  1021. Button:Initialise(9, 4, nil, nil, nil, nil, resetSideToggle, 'Front', colours.black, false, colours.green),
  1022. Button:Initialise(2, 6, nil, nil, nil, nil, resetSideToggle, 'Left', colours.black, false, colours.green),
  1023. Button:Initialise(9, 6, nil, nil, nil, nil, resetSideToggle, 'Right', colours.black, false, colours.green),
  1024. Button:Initialise(2, 8, nil, nil, nil, nil, resetSideToggle, 'Top', colours.black, false, colours.green),
  1025. Button:Initialise(8, 8, nil, nil, nil, nil, resetSideToggle, 'Bottom', colours.black, false, colours.green)
  1026. }
  1027. for i, v in ipairs(sideButtons) do
  1028. if v.Text:lower() == Current.Settings.RedstoneSide then
  1029. v.Toggle = true
  1030. end
  1031. table.insert(Current.PageControls, v)
  1032. end
  1033.  
  1034. local distanceButtons = {}
  1035. local function resetDistanceToggle(self)
  1036. for i, v in ipairs(distanceButtons) do
  1037. if v.Toggle ~= nil then
  1038. v.Toggle = false
  1039. end
  1040. end
  1041. if self.Text == 'Small' then
  1042. Current.Settings.Distance = 5
  1043. elseif self.Text == 'Normal' then
  1044. Current.Settings.Distance = 10
  1045. elseif self.Text == 'Far' then
  1046. Current.Settings.Distance = 15
  1047. end
  1048. SaveSettings()
  1049. end
  1050.  
  1051. table.insert(Current.PageControls, Label:Initialise(23, 2, 'Opening Distance'))
  1052. distanceButtons = {
  1053. Button:Initialise(23, 4, nil, nil, nil, nil, resetDistanceToggle, 'Small', colours.black, false, colours.green),
  1054. Button:Initialise(31, 4, nil, nil, nil, nil, resetDistanceToggle, 'Normal', colours.black, false, colours.green),
  1055. Button:Initialise(40, 4, nil, nil, nil, nil, resetDistanceToggle, 'Far', colours.black, false, colours.green)
  1056. }
  1057. for i, v in ipairs(distanceButtons) do
  1058. if v.Text == 'Small' and Current.Settings.Distance == 5 then
  1059. v.Toggle = true
  1060. elseif v.Text == 'Normal' and Current.Settings.Distance == 10 then
  1061. v.Toggle = true
  1062. elseif v.Text == 'Far' and Current.Settings.Distance == 15 then
  1063. v.Toggle = true
  1064. end
  1065. table.insert(Current.PageControls, v)
  1066. end
  1067.  
  1068. table.insert(Current.PageControls, Label:Initialise(2, 10, 'Registered PDAs: '..#Current.Settings.Whitelist))
  1069. table.insert(Current.PageControls, Button:Initialise(2, 12, nil, nil, nil, nil, function()Current.Settings.Whitelist = {}HostSetup()end, 'Unregister All', colours.black))
  1070.  
  1071.  
  1072. table.insert(Current.PageControls, Label:Initialise(23, 6, 'Help', colours.black))
  1073. local helpLines = {
  1074. Label:Initialise(23, 8, 'To register a new PDA simply', colours.black),
  1075. Label:Initialise(23, 9, 'place a Disk Drive next to', colours.black),
  1076. Label:Initialise(23, 10, 'the computer, then put the', colours.black),
  1077. Label:Initialise(23, 11, 'PDA in the Drive, it will', colours.black),
  1078. Label:Initialise(23, 12, 'register automatically. If', colours.black),
  1079. Label:Initialise(23, 13, 'it worked it will eject.', colours.black),
  1080. Label:Initialise(23, 15, 'Make sure you hide this', colours.red),
  1081. Label:Initialise(23, 16, 'computer away from the', colours.red),
  1082. Label:Initialise(23, 17, 'door! (other people)', colours.red)
  1083. }
  1084. for i, v in ipairs(helpLines) do
  1085. table.insert(Current.PageControls, v)
  1086. end
  1087.  
  1088.  
  1089. table.insert(Current.PageControls, Button:Initialise(2, 14, nil, nil, nil, nil, function()
  1090. for i = 1, 6 do
  1091. helpLines[i].TextColour = colours.green
  1092. end
  1093. end, 'Register New PDA', colours.black))
  1094.  
  1095. end
  1096.  
  1097. function HostStatusPage()
  1098. ResetPage()
  1099. Current.Page = 'HostStatus'
  1100. Current.StatusScreen = true
  1101. Current.ButtonOne = Button:Initialise(Drawing.Screen.Width - 6, Drawing.Screen.Height - 1, nil, nil, nil, nil, Quit, 'Quit', colours.black)
  1102. Current.ButtonTwo = Button:Initialise(2, Drawing.Screen.Height - 1, nil, nil, nil, nil, HostSetup, 'Settings/Help', colours.black)
  1103.  
  1104. Wireless.Responder = function(event, side, channel, replyChannel, message, distance)
  1105. if channel == Wireless.Channels.UltimateDoorlockRequest and distance < Current.Settings.Distance then
  1106. if FingerprintIsOnWhitelist(message.content) then
  1107. OpenDoor()
  1108. Wireless.SendMessage(Wireless.Channels.UltimateDoorlockRequestReply, true)
  1109. else
  1110. Wireless.SendMessage(Wireless.Channels.UltimateDoorlockRequestReply, false)
  1111. end
  1112. end
  1113. end
  1114.  
  1115. PingPocketComputers()
  1116. end
  1117.  
  1118. function HostInitialise()
  1119. if not Wireless.Present() then
  1120. Current.Locked = true
  1121. Current.ButtonOne = Button:Initialise(Drawing.Screen.Width - 6, Drawing.Screen.Height - 1, nil, nil, nil, nil, Quit, 'Quit', colours.black)
  1122. Current.ButtonTwo = Button:Initialise(2, Drawing.Screen.Height - 1, nil, nil, nil, nil, function()os.reboot()end, 'Reboot', colours.black)
  1123. ResetStatus()
  1124. return
  1125. end
  1126. Wireless.Initialise()
  1127. ResetStatus()
  1128. if fs.exists('.settings') then
  1129. local h = fs.open('.settings', 'r')
  1130. if h then
  1131. Current.Settings = textutils.unserialize(h.readAll())
  1132. end
  1133. h.close()
  1134. HostStatusPage()
  1135. else
  1136. HostSetup()
  1137. end
  1138. if OneOS then
  1139. OneOS.CanClose = function()
  1140. CloseDoor()
  1141. return true
  1142. end
  1143. end
  1144. end
  1145.  
  1146. local pingTimer = nil
  1147. function PingPocketComputers()
  1148. Wireless.SendMessage(Wireless.Channels.UltimateDoorlockPing, 'Ping!', Wireless.Channels.UltimateDoorlockRequest)
  1149. pingTimer = os.startTimer(0.5)
  1150. end
  1151.  
  1152. function Initialise(arg)
  1153. EventRegister('mouse_click', TryClick)
  1154. EventRegister('mouse_drag', function(event, side, x, y)TryClick(event, side, x, y, true)end)
  1155. EventRegister('mouse_scroll', Scroll)
  1156. EventRegister('key', HandleKey)
  1157. EventRegister('char', HandleKey)
  1158. EventRegister('timer', Timer)
  1159. EventRegister('terminate', function(event) if Close() then error( "Terminated", 0 ) end end)
  1160. EventRegister('modem_message', Wireless.HandleMessage)
  1161. EventRegister('disk', RegisterPDA)
  1162.  
  1163. if OneOS then
  1164. OneOS.RequestRunAtStartup()
  1165. end
  1166.  
  1167. if pocket then
  1168. PocketInitialise()
  1169. else
  1170. HostInitialise()
  1171. end
  1172.  
  1173.  
  1174. Draw()
  1175.  
  1176. EventHandler()
  1177. end
  1178.  
  1179. function Timer(event, timer)
  1180. if timer == pingTimer then
  1181. PingPocketComputers()
  1182. elseif timer == closeDoorTimer then
  1183. CloseDoor()
  1184. elseif timer == statusResetTimer then
  1185. ResetStatus()
  1186. end
  1187. end
  1188.  
  1189. local ignoreNextChar = false
  1190. function HandleKey(...)
  1191. local args = {...}
  1192. local event = args[1]
  1193. local keychar = args[2]
  1194. --[[
  1195. --Mac left command character
  1196. if event == 'key' and keychar == keys.leftCtrl or keychar == keys.rightCtrl or keychar == 219 then
  1197. isControlPushed = true
  1198. controlPushedTimer = os.startTimer(0.5)
  1199. elseif isControlPushed then
  1200. if event == 'key' then
  1201. if CheckKeyboardShortcut(keychar) then
  1202. isControlPushed = false
  1203. ignoreNextChar = true
  1204. end
  1205. end
  1206. elseif ignoreNextChar then
  1207. ignoreNextChar = false
  1208. elseif Current.TextInput then
  1209. if event == 'char' then
  1210. Current.TextInput:Char(keychar)
  1211. elseif event == 'key' then
  1212. Current.TextInput:Key(keychar)
  1213. end
  1214. end
  1215. ]]--
  1216. end
  1217.  
  1218. --[[
  1219. Check if the given object falls under the click coordinates
  1220. ]]--
  1221. function CheckClick(object, x, y)
  1222. if object.X <= x and object.Y <= y and object.X + object.Width > x and object.Y + object.Height > y then
  1223. return true
  1224. end
  1225. end
  1226.  
  1227. --[[
  1228. Attempt to clicka given object
  1229. ]]--
  1230. function DoClick(object, side, x, y, drag)
  1231. local obj = GetAbsolutePosition(object)
  1232. obj.Width = object.Width
  1233. obj.Height = object.Height
  1234. if object and CheckClick(obj, x, y) then
  1235. return object:Click(side, x - object.X + 1, y - object.Y + 1, drag)
  1236. end
  1237. end
  1238.  
  1239. --[[
  1240. Try to click at the given coordinates
  1241. ]]--
  1242. function TryClick(event, side, x, y, drag)
  1243. if Current.ButtonOne then
  1244. if DoClick(Current.ButtonOne, side, x, y, drag) then
  1245. Draw()
  1246. return
  1247. end
  1248. end
  1249.  
  1250. if Current.ButtonTwo then
  1251. if DoClick(Current.ButtonTwo, side, x, y, drag) then
  1252. Draw()
  1253. return
  1254. end
  1255. end
  1256.  
  1257. for i, v in ipairs(Current.PageControls) do
  1258. if DoClick(v, side, x, y, drag) then
  1259. Draw()
  1260. return
  1261. end
  1262. end
  1263.  
  1264. Draw()
  1265. end
  1266.  
  1267. function Scroll(event, direction, x, y)
  1268. if Current.Window and Current.Window.OpenButton then
  1269. Current.Document.Scroll = Current.Document.Scroll + direction
  1270. if Current.Window.Scroll < 0 then
  1271. Current.Window.Scroll = 0
  1272. elseif Current.Window.Scroll > Current.Window.MaxScroll then
  1273. Current.Window.Scroll = Current.Window.MaxScroll
  1274. end
  1275. Draw()
  1276. elseif Current.ScrollBar then
  1277. if Current.ScrollBar:DoScroll(direction*2) then
  1278. Draw()
  1279. end
  1280. end
  1281. end
  1282.  
  1283. --[[
  1284. Registers functions to run on certain events
  1285. ]]--
  1286. function EventRegister(event, func)
  1287. if not Events[event] then
  1288. Events[event] = {}
  1289. end
  1290.  
  1291. table.insert(Events[event], func)
  1292. end
  1293.  
  1294. --[[
  1295. The main loop event handler, runs registered event functinos
  1296. ]]--
  1297. function EventHandler()
  1298. while isRunning do
  1299. local event, arg1, arg2, arg3, arg4, arg5, arg6 = os.pullEventRaw()
  1300. if Events[event] then
  1301. for i, e in ipairs(Events[event]) do
  1302. e(event, arg1, arg2, arg3, arg4, arg5, arg6)
  1303. end
  1304. end
  1305. end
  1306. end
  1307.  
  1308. function Quit()
  1309. isRunning = false
  1310. term.setCursorPos(1,1)
  1311. term.setBackgroundColour(colours.black)
  1312. term.setTextColour(colours.white)
  1313. term.clear()
  1314. if OneOS then
  1315. OneOS.Close()
  1316. end
  1317. end
  1318.  
  1319. if not term.current then -- if not 1.6
  1320. print('Because it requires pocket computers, Ultimate Door Lock requires ComputerCraft 1.6. Please update to 1.6 to use Ultimate Door Lock.')
  1321. elseif not (OneOS and pocket) and term.isColor and term.isColor() then
  1322. -- If the program crashes close the door and reboot
  1323. local _, err = pcall(Initialise)
  1324. if err then
  1325. CloseDoor()
  1326. term.setCursorPos(1,1)
  1327. term.setBackgroundColour(colours.black)
  1328. term.setTextColour(colours.white)
  1329. term.clear()
  1330. print('Ultimate Door Lock has crashed')
  1331. print('To maintain security, the computer will reboot.')
  1332. print('If you are seeing this alot try turning off all Pocket Computers or reinstall.')
  1333. print()
  1334. print('Error:')
  1335. printError(err)
  1336. sleep(5)
  1337. os.reboot()
  1338. end
  1339. elseif OneOS and pocket then
  1340. term.setCursorPos(1,3)
  1341. term.setBackgroundColour(colours.white)
  1342. term.setTextColour(colours.blue)
  1343. term.clear()
  1344. print('OneOS already acts as a door key. Simply place your PDA in the door\'s disk drive to register it.')
  1345. print()
  1346. print('To setup a door, run this program on an advanced computer (non-pocket).')
  1347. print()
  1348. print('Click anywhere to quit')
  1349. os.pullEvent('mouse_click')
  1350. Quit()
  1351. else
  1352. print('Ultimate Door Lock requires an advanced (gold) computer or pocket computer.')
  1353. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement