Advertisement
MoonlightOwl

SpiderEye Terminal by Totoro

Sep 11th, 2014
1,234
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 10.83 KB | None | 0 0
  1. -- Totoro SpiderEye Terminal -- v.3 --
  2.  
  3. serial = require('serialization')
  4. fs = require('filesystem')
  5. event = require('event')
  6. sides = require('sides')
  7. term = require('term')
  8. com = require('component')
  9. gpu = com.gpu
  10. red = com.redstone
  11.  
  12. --  Parameters  --
  13. owner = "Totoro"
  14. monsterlist = {"Spider", "Zombie", "Creeper", "Skeleton", "Enderman", "Sheep", "Cow", "Chicken"}
  15. howlerside = sides.back
  16. cooldown = 100
  17.  
  18. --    Colors   --
  19. backcolor = 0x000000
  20. forecolor = 0xFFFFFF
  21. infocolor = 0x0066FF
  22. errorcolor = 0xFF0000
  23. truecolor = 0x00FF00
  24. --     ****     --
  25.  
  26. -- vars
  27. monsters = false
  28. whitelist = {owner}
  29. sensors = {}
  30. log = {}
  31.  
  32. -- init graphics
  33. oldw, oldh = gpu.getResolution()
  34. width, height = gpu.maxResolution()
  35. gpu.setResolution(width, height)
  36. gpu.setForeground(forecolor)
  37. gpu.setBackground(backcolor)
  38.  
  39. loglen = height-4
  40.  
  41. -- create folder for logs
  42. if not fs.exists("logs") then
  43.   fs.makeDirectory("logs")
  44. end
  45.  
  46. function clear(x, y, w, h)
  47.   gpu.fill(x, y, w, h, " ")
  48. end
  49.  
  50. local strLine = "+"
  51. for i=1, width do
  52.   strLine = strLine..'-'
  53. end
  54. function line(x1, x2, y)
  55.   gpu.set(x1,y,string.sub(strLine, 1, x2-x1))
  56.   gpu.set(x2,y,'+')
  57. end
  58.  
  59. function frame(x1, y1, x2, y2, caption)
  60.   line(x1, x2, y1)
  61.   line(x1, x2, y2)
  62.  
  63.   if caption ~= nil then
  64.     gpu.set(x1+(x2-x1)/2-#caption/2, y1, caption)
  65.   end
  66. end
  67.  
  68. function center(y, text)
  69.   gpu.set(width/2-#text/2, y, text)
  70. end
  71.  
  72. -- screens
  73. function drawLog()
  74.   for y=1, #log do
  75.     gpu.set(6, y+2, log[y])
  76.   end
  77. end
  78. function drawlist()
  79.   for y=3, height-3 do
  80.     if y-2>#sensors then break end
  81.  
  82.     local xx = 6+math.floor(y/loglen)*(width/2-8)
  83.     local yy = y-math.floor(y/loglen)*(loglen-1)
  84.     -- color indication
  85.     if sensors[y-2].time > 5 then
  86.       gpu.setBackground(0xFF0000)
  87.       gpu.set(xx, yy, sensors[y-2].name..': '..sensors[y-2].entity)
  88.       gpu.setBackground(0x000000)
  89.     elseif sensors[y-2].time >0 then
  90.       gpu.setBackground(0xFFFF00)
  91.       gpu.set(xx, yy, sensors[y-2].name..': '..sensors[y-2].entity)
  92.       gpu.setBackground(0x000000)
  93.     else
  94.       gpu.set(xx, yy, sensors[y-2].name)
  95.     end
  96.   end
  97. end
  98. function drawWhitelist()
  99.   for y=1, #whitelist do
  100.     gpu.set(6+math.floor(y/loglen)*(width/3), y+2-math.floor(y/loglen)*(loglen-1), whitelist[y])
  101.   end
  102. end
  103.  
  104. function mainframe()
  105.   term.clear()
  106.   frame(2,1, width-1, height, "{ SpiderEye Terminal }")
  107.  
  108.   drawlist()
  109.  
  110.   if monsters then gpu.set(2, height-1, "M") end
  111.   gpu.set(4, height-1, "[Info] Press 'H' for help, 'Q' for exit")
  112. end
  113. function logframe()
  114.   term.clear()
  115.   frame(2,1, width-1, height, "{ SpiderEye Log }")
  116.  
  117.   drawLog()
  118.  
  119.   if monsters then gpu.set(2, height-1, "M") end
  120.   gpu.set(4, height-1, "[Info] Press 'H' for help, 'Q' for exit")
  121. end
  122.  
  123. function helpframe()
  124.   term.clear()
  125.   frame(2,1, width-1, height, "{ SpiderEye Help }")
  126.   center(3, "Controls")
  127.   gpu.set(8, 5, "'H' - Show/hide help")
  128.   gpu.set(8, 6, "'L' - Show/hide log")
  129.   gpu.set(8, 7, "'W' - Show/hide whitelist")
  130.   gpu.set(8, 8, "'A' - Add new motion sensor/whitelist user")
  131.   gpu.set(8, 9, "'D' - Delete sensor/whitelist user")
  132.   gpu.set(8, 10, "'R' - Refresh sensors list")
  133.   gpu.set(8, 11, "'M' - Allow monsters detection")
  134.   gpu.set(8, 12, "'Q' - Exit SpiderEye")
  135.   center(height-6, "About")
  136.   center(height-4, "Programmer:    Totoro")
  137.   center(height-3, "9/8/2014, MIT license")
  138.   center(height-2, "moonlightowl@creep.im")
  139.   if monsters then gpu.set(2, height-1, "M") end
  140. end
  141.  
  142. function whiteframe()
  143.   term.clear()
  144.   frame(2,1, width-1, height, "{ SpiderEye WhiteList }")
  145.  
  146.   drawWhitelist()
  147.  
  148.   if monsters then gpu.set(2, height-1, "M") end
  149.   gpu.set(4, height-1, "[Info] Press 'H' for help, 'Q' for exit")
  150. end
  151.  
  152. function getBox(title)
  153.   clear(1, height/2-2, width, 5)
  154.   line(2, width-1, height/2-2)
  155.   line(2, width-1, height/2+2)
  156.  
  157.   gpu.set(6, height/2-2, title)
  158.   term.setCursor(5, height/2)
  159.  
  160.   return string.sub(term.read(), 1, -2)
  161. end
  162.  
  163. function addSensor()
  164.   local new = {}
  165.  
  166.   new.address = getBox("[ Enter address: ]")
  167.   if new.address == nil or new.address == '' then return end
  168.  
  169.   -- check address
  170.   test = com.get(new.address)
  171.   if test == nil then
  172.     message("Address "..new.address.." not found!", errorcolor)
  173.     return
  174.   else
  175.     new.address = test
  176.   end
  177.  
  178.   new.name = getBox("[ Enter codename: ]")
  179.   if new.name == nil or new.name == '' then return end
  180.  
  181.   -- add new sensor
  182.   new.entity = "None"
  183.   new.time = 0
  184.   table.insert(sensors, new)
  185.   message("New sensor in table!", infocolor)
  186. end
  187.  
  188. function addWhitelist()
  189.   name = getBox("[ Enter nickname: ]")
  190.   if name == nil or name == '' then return end
  191.  
  192.   table.insert(whitelist, name)
  193.   message("User "..name.." in whitelist!", infocolor)
  194. end
  195.  
  196. function removeSensor()
  197.   code = getBox("[ Deletion. Enter name or address: ]")
  198.   if code == nil or code == '' then return end
  199.  
  200.   for i=1, #sensors do
  201.     if string.sub(sensors[i].address, 1, #code) == code
  202.         or sensors[i].name == code then
  203.       table.remove(sensors, i)
  204.       message("Sensor "..code.." deleted!", infocolor)
  205.       return
  206.     end
  207.   end
  208.   message("No "..code.." sensor found!", errorcolor)
  209. end
  210.  
  211. function removeWhitelist()
  212.   code = getBox("[ Deletion. Enter nickname: ]")
  213.   if code == nil or code == '' then return end
  214.  
  215.   for i=1, #whitelist do
  216.     if whitelist[i] == code then
  217.       table.remove(whitelist, i)
  218.       message("User "..code.." deleted!", infocolor)
  219.       return
  220.     end
  221.   end
  222.   message("No "..code.." in whitelist found!", errorcolor)
  223. end
  224.  
  225. function message(text, color)
  226.   local off = width/2-#text/2
  227.   gpu.setBackground(color)
  228.   clear(off-2, height/2-1, #text+4, 3)
  229.   frame(off-2, height/2-1, off+#text+1, height/2+1)
  230.   gpu.set(off, height/2, text)
  231.   gpu.setBackground(backcolor)
  232.   message_visible = true
  233. end
  234.  
  235. function redraw()
  236.   if state == 0 then mainframe()
  237.   elseif state == 1 then helpframe()
  238.   elseif state == 3 then logframe()
  239.   elseif state == 4 then whiteframe() end
  240. end
  241.  
  242. -- processing
  243. function getName(add)
  244.   for i=1, #sensors do
  245.     if add == sensors[i].address then
  246.       return sensors[i].name
  247.     end
  248.   end
  249.   return 'Unknown'
  250. end
  251. function intruder(add, name)
  252.   for i=1, #sensors do
  253.     if add == sensors[i].address then
  254.       if sensors[i].entity ~= name or sensors[i].time == 0 then
  255.         toLog(os.date().." / Motion in "..sensors[i].name..": "..name)
  256.       end
  257.       sensors[i].entity = name
  258.       sensors[i].time = cooldown
  259.       break
  260.     end
  261.   end
  262. end
  263.  
  264. function update()
  265.   local calm = true
  266.   for i=1, #sensors do
  267.     if sensors[i].time>0 then
  268.       sensors[i].time = sensors[i].time-1
  269.       calm = false
  270.     end
  271.   end
  272.   if calm and howling then howl(false) end
  273. end
  274. function refresh()
  275.   local all_right = true
  276.   if sensors ~= nil then
  277.     for i=#sensors, 1, -1 do
  278.       if com.get(sensors[i].address) == nil then
  279.         message("Sensor '"..sensors[i].address.."' not found!", errorcolor)
  280.         table.remove(sensors, i)
  281.         all_right = false
  282.       end
  283.     end
  284.   end
  285.   if all_right then message("All is right!", truecolor) end
  286. end
  287.  
  288. function toLog(message)
  289.   if #log < loglen then
  290.     table.insert(log, message)
  291.   else
  292.     for c=1, loglen-1 do
  293.       log[c] = log[c+1]
  294.     end
  295.     log[loglen] = message
  296.   end
  297.  
  298.   local name = 'logs/'..string.gsub(os.date('%x'), '/', '_')..'.log'
  299.   local file = nil
  300.   if fs.exists(name) then
  301.     file = io.open(name, 'a')
  302.   else
  303.     file = io.open(name, 'w')
  304.   end
  305.   file:write(message..'\n')
  306.   file:close()
  307. end
  308.  
  309. function whitelisted(name)
  310.   if not monsters then
  311.     for i=1, #monsterlist do
  312.       if name == monsterlist[i] then return true end
  313.     end
  314.   end
  315.   for i=1, #whitelist do
  316.     if name == whitelist[i] then return true end
  317.   end
  318.   return false
  319. end
  320. function howl(active)
  321.   -- any redstone controller?
  322.   if red ~= nil then
  323.     -- then emit!
  324.     if active then
  325.       if not howling then
  326.         red.setOutput(howlerside, 15)
  327.         howling = true
  328.       end
  329.     elseif howling then
  330.       red.setOutput(howlerside, 0)
  331.       howling = false
  332.     end
  333.   end
  334. end
  335.  
  336.  
  337. -- load and save data
  338. function loadSensorlist()
  339.   if fs.exists("senslist.txt") then
  340.     local file = io.open("senslist.txt", "r")
  341.     local data = file:read("*a")
  342.     sensors = serial.unserialize(data)
  343.     file:close()
  344.     if sensors == nil then sensors = {} end
  345.     refresh()
  346.   end
  347. end
  348. function saveSensorlist()
  349.   local file = io.open("senslist.txt", "w")
  350.   local data = serial.serialize(sensors)
  351.   file:write(data)
  352.   file:close()
  353. end
  354. function loadWhitelist()
  355.   if fs.exists("whitelist.txt") then
  356.     local file = io.open("whitelist.txt", "r")
  357.     local data = file:read("*a")
  358.     whitelist = serial.unserialize(data)
  359.     file:close()
  360.     if whitelist == nil then whitelist = {owner} end
  361.   end
  362. end
  363. function saveWhitelist()
  364.   local file = io.open("whitelist.txt", "w")
  365.   local data = serial.serialize(whitelist)
  366.   file:write(data)
  367.   file:close()
  368. end
  369.  
  370.  
  371. -- init
  372. loadSensorlist()
  373. loadWhitelist()
  374. mainframe()
  375. state = 0   -- 0-main; 1-help; 3-log; 4-whitelist
  376. message_visible = false
  377. howling = false
  378.  
  379. while true do
  380.   name, add, a, b, c, d = event.pull(0.1)
  381.   if b~=nil then
  382.     --print(a, b, c)
  383.   end
  384.   if name == 'key_down' then
  385.     if message_visible then          -- hide message
  386.       redraw()
  387.       message_visible = false
  388.     elseif b == 35 then         -- 'H' - help
  389.       if state~=1 then
  390.         helpframe()
  391.         state = 1
  392.       else
  393.         mainframe()
  394.         state = 0
  395.       end
  396.     elseif b == 38 then         -- 'L' - log
  397.       if state~=3 then
  398.         logframe()
  399.         state = 3
  400.       else
  401.         mainframe()
  402.         state = 0
  403.       end
  404.     elseif b == 17 then         -- 'W' - whitelist
  405.       if state~=4 then
  406.         whiteframe()
  407.         state = 4
  408.       else
  409.         mainframe()
  410.         state = 0
  411.       end
  412.     elseif b == 30 then         -- 'A' - add new sensor/user
  413.       if state ~= 4 then
  414.         addSensor()
  415.       else
  416.         addWhitelist()
  417.       end
  418.       if not message_visible then redraw() end
  419.     elseif b == 32 then         -- 'D' - delete sensor/user from list
  420.       if state ~= 4 then
  421.         removeSensor()
  422.       else
  423.         removeWhitelist()
  424.       end
  425.       if not message_visible then redraw() end
  426.     elseif b == 19 then         -- 'R' - refresh sensors list
  427.       refresh()
  428.     elseif b == 50 then         -- 'M' - allow monster detection
  429.       monsters = not monsters
  430.       -- draw indicator
  431.       if monsters then gpu.set(2, height-1, "M")
  432.       else gpu.set(2, height-1, " ") end
  433.     elseif b == 16 then break   -- 'Q' - exit SpiderEye
  434.     end
  435.   elseif name == 'motion' then
  436.     if not whitelisted(d) then
  437.       intruder(add, d)
  438.       howl(true)
  439.     end
  440.     if d ~= owner then message("Motion in "..getName(add)..": "..d, errorcolor) end
  441.   end
  442.   update()
  443. end
  444.  
  445. -- end
  446. gpu.setResolution(oldw, oldh)
  447. term.clear()
  448. saveSensorlist()
  449. saveWhitelist()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement