Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- SmartLock 0.3 --
- -- advances lock system by Totoro; 10/01/2014 --
- local event = require('event')
- local serial = require('serialization')
- local sides = require('sides')
- local term = require('term')
- local fs = require('filesystem')
- local com = require('component')
- local comp = require('computer')
- -- Таблица констант --
- OWNER = 'Totoro'
- DEFAULT_USER = 'Noname'
- DEFAULT_LEVEL = 1
- DEFAULT_DOOR = 'Door X'
- OPEN_TIME = 1
- RED_STRENGTH = 1
- PORT = 27
- ALLOW = "。◕‿◕。"
- WAIT = "(⊙_◎)"
- DENY = "(¬_¬)"
- GLASSX = 240
- GLASSY = 55
- GLASS_TIME = 2
- -- Таблица цветов --
- forecolor = 0xFFFFFF
- backcolor = 0x000000
- allowcolor = 0x00FF00
- errorcolor = 0xFF0000
- warncolor = 0xCCCC00
- infocolor = 0x398eb5
- --
- function trytofind(name)
- if com.isAvailable(name) then
- return com.getPrimary(name)
- else
- return nil
- end
- end
- local modem = trytofind('modem')
- local glass = trytofind('openperipheral_glassesbridge')
- local mgpu = trytofind('gpu')
- term.clear()
- function errout(message)
- mgpu.setForeground(errorcolor)
- print('[ERROR] '..message)
- mgpu.setForeground(forecolor)
- end
- function warnout(message)
- mgpu.setForeground(warncolor)
- print('[WARNING] '..message)
- mgpu.setForeground(forecolor)
- end
- function infout(message)
- mgpu.setForeground(infocolor)
- print('[INFO] '..message)
- mgpu.setForeground(forecolor)
- end
- local agpu = nil
- for a,b in com.list('gpu') do
- if a ~= mgpu.address then agpu = com.proxy(a); break end
- end
- if agpu == nil then
- errout("Не обнаружена вторая видеокарта!")
- return
- end
- if modem ~= nil then infout("Обнаружен модем. Активирован сетевой интерфейс.") end
- if glass ~= nil then infout("Вы можете использовать удаленный интерфейс через очки.")
- else warnout("Очки не обнаружены. Удаленный интерфейс недоступен.") end
- width, height = mgpu.getResolution()
- -- создаем папку для логов
- if not fs.exists("logs") then
- fs.makeDirectory("logs")
- end
- -- ======================================== L I S T M A N A G E R S ======================================== --
- function readList(filename)
- if fs.exists(filename) then
- local file = io.open(filename, "r")
- local data = file:read("*a")
- local list = serial.unserialize(data)
- file:close()
- return list
- else
- errout("Файл "..filename.." не найден, создан пустой список!")
- return {}
- end
- end
- function saveList(list, filename)
- local file = io.open(filename, "w")
- data = serial.serialize(list)
- file:write(data)
- file:close()
- end
- function toList(list, name, data)
- if data == nil then data = true end
- list[name] = data
- return true
- end
- function fromList(list, name)
- if list[name] then
- list[name] = nil
- return true
- end
- return false
- end
- function contains(list, name)
- return list[name] ~= nil
- end
- function printlist(list)
- if next(list) == nil then print("Таблица пуста.")
- else
- c = 1
- for a,b in pairs(list) do
- print(a, b)
- c = c + 1
- if c > height-3 then
- print("Любая клавиша для продолжения...")
- event.pull('key_down')
- c = 1
- end
- end
- end
- end
- -- ================================================= L O G S ================================================= --
- log = {}
- log_new = 1
- function toLog(message)
- table.insert(log, message)
- local name = 'logs/'..string.gsub(os.date('%x'), '/', '_')..'.log'
- local file = nil
- if fs.exists(name) then
- file = io.open(name, 'a')
- else
- file = io.open(name, 'w')
- end
- file:write(message..'\n')
- file:close()
- end
- function printlog(index)
- if index == nil then
- infout(" Лог событий (целиком):")
- else
- infout(" Лог событий (новое):")
- end
- c = 0
- for i=index or 1, #log do
- print(log[i])
- c = c + 1
- if c > height-3 then
- print("Любая клавиша для продолжения...")
- event.pull('key_down')
- c = 1
- end
- end
- if c == 0 then print("Лог пуст.") end
- log_new = #log + 1
- end
- -- =========================================== P R O C E S S I N G =========================================== --
- function trytoopen(data)
- if data == nil then
- if last_door ~= nil then
- ginfout("Открыто: "..doorlist[last_door].name)
- open(last_door)
- else
- gerrout("Уточните код замка.")
- end
- else
- local screen = com.get(data)
- if screen == nil then
- gerrout("Замок "..data.." не найден.")
- else
- if contains(doorlist, screen) then
- open(screen)
- ginfout("Открыто: "..doorlist[screen].name)
- else
- gerrout("Замок отсутствует в таблице.")
- end
- end
- end
- end
- function split(str)
- local result = {}
- for i in string.gmatch(str, "%S+") do
- table.insert(result, i)
- end
- return result
- end
- function process(command, console)
- -- разбивка строки-команды
- local data = split(command)
- -- команда на открытие двери
- if data[1] == 'open' then
- trytoopen(data[2])
- -- добавление нового игрока в таблицу / изменение существующего
- elseif data[1] == 'set' or data[1] == 'user' then
- local name = data[2] or DEFAULT_USER
- local level = tonumber(data[3]) or DEFAULT_LEVEL
- toList(userlist, name, level)
- ginfout("Уровень доступа "..name..": "..level)
- -- добавление новой двери в список / изменение уровня или названия существующей
- elseif data[1] == 'door' then
- local screen = com.get(data[2], 'screen')
- if screen == nil then
- gerrout("Монитор с адресом "..data[2].." не найден.")
- else
- local red = com.get(data[3], 'redstone')
- if red == nil then
- if contains(doorlist, screen) then
- local level = tonumber(data[3])
- if level == nil then
- doorlist[screen].name = data[3]
- ginfout("Название для "..string.sub(screen, 1, 4).." изменено: "..data[3].." ("..doorlist[screen].level..")")
- else
- doorlist[screen].level = level
- ginfout("Уровень изменен: "..doorlist[screen].name.." ("..level..")")
- end
- else
- gerrout("Этот монитор отсутствует в таблице.")
- end
- else
- local name = data[4] or DEFAULT_DOOR
- local level = tonumber(data[5]) or DEFAULT_LEVEL
- toList(doorlist, screen, {name = name, red = red, level = level})
- ginfout("Новый замок: "..name.." ("..level..")")
- end
- end
- -- вывод на экран/очки списков
- elseif data[1] == 'list' then
- if data[2] == 'door' or data[2] == 'doors' then
- if next(doorlist) == nil then ginfout("Таблица пуста.")
- else
- ginfout(" Таблица замков:")
- for a,b in pairs(doorlist) do
- print(string.sub(a, 1, 4), string.sub(b.red, 1, 4), b.name, b.level)
- end
- end
- else
- ginfout(" Таблица пользователей:")
- printlist(userlist)
- end
- elseif data[1] == 'get' then
- if contains(userlist, data[2]) then
- ginfout("Пользователь "..data[2]..", уровень доступа "..userlist[data[2]])
- else
- local screen = com.get(data[2], 'screen')
- if screen ~= nil then
- if contains(doorlist, screen) then
- ginfout("\n"..string.sub(screen, 1, 4), string.sub(doorlist[screen].red, 1, 4), doorlist[screen].name, doorlist[screen].level)
- else
- gerrout("Этот замок в таблице отсутствует.")
- end
- else
- gerrout("Такого не существует.")
- end
- end
- -- удаление двери или игрока из списка
- elseif data[1] == 'delete' or data[1] == 'remove' then
- local screen = com.get(data[2], 'screen')
- if screen == nil then
- if contains(userlist, data[2]) then
- fromList(userlist, data[2])
- ginfout("Игрок "..data[2].." успешно удален из списка.")
- else
- gerrout("Неверное имя/адрес.")
- end
- else
- fromList(doorlist, screen)
- ginfout("Замок по адресу "..data[2].." успешно удален из списка.")
- end
- -- вывод лога
- elseif data[1] == 'log' then
- if data[2] == 'clear' then
- log = {}
- log_new = 1
- ginfout("Лог очищен.")
- elseif data[2] == 'all' then
- printlog()
- else
- printlog(log_new)
- end
- -- выход из программы
- elseif data[1] == 'exit' or data[1] == 'quit' or data[1] == 'q' then return false
- else gerrout("Команда не знакома.") end
- -- успешное выполнение
- return true
- end
- function open(address, flag)
- local red = com.proxy(doorlist[address].red)
- if red == nil then
- gerrout("Проверьте данные для "..doorlist[address].name.." ("..string.sub(address, 1, 4)..")!")
- else
- -- если дверь открывается - показываем смайлик и записываем время
- if not flag then
- show(address, ALLOW)
- doorlist[address].time = comp.uptime()
- end
- for i=0, 5 do
- if flag then
- red.setOutput(i, 0)
- else
- red.setOutput(i, RED_STRENGTH)
- end
- end
- end
- end
- -- ============================================ E M O T I C O N S ============================================ --
- function show(address, str)
- agpu.bind(address)
- agpu.setResolution(5,1)
- if str == ALLOW then
- agpu.setForeground(allowcolor)
- elseif str == WAIT then
- agpu.setForeground(warncolor)
- else
- agpu.setForeground(errorcolor)
- end
- agpu.set(1, 1, str)
- end
- -- ============================================== G L A S S E S ============================================== --
- glass_uptime = 0
- function glass_clear()
- if glass ~= nil then
- glass.clear()
- end
- end
- function glass_addText(x, y, text, color)
- if glass ~= nil then
- obj = {}
- obj[0] = glass.addText(x+1, y+1, text, 0x000000)
- obj[1] = glass.addText(x, y, text, color)
- return obj
- end
- end
- function glass_splash(message, app)
- if glass ~= nil then
- glass_clear()
- local width = #message*5.3; title = '[ Message ]'; color = 0xFFFFFF
- x = GLASSX - width/2; y = GLASSY-10
- if app == 0 then
- color = infocolor
- title = '[ INFO ]'
- elseif app == 1 then
- color = warncolor
- title = '[ WARNING ]'
- else
- color = errorcolor
- title = '[ ERROR ]'
- end
- glass.addBox(x, y, width, 20, color, 0.5)
- glass_addText(GLASSX - 17, GLASSY-11, title, 0xFFFFFF)
- glass_addText(x+10, GLASSY, message, 0xFFFFFF)
- glass_uptime = comp.uptime()
- end
- end
- function ginfout(message)
- infout(message)
- glass_splash(message, 0)
- end
- function gwarnout(message)
- warnout(message)
- glass_splash(message, 1)
- end
- function gerrout(message)
- errout(message)
- glass_splash(message, 2)
- end
- -- ======================================== N E T I N T E R F A C E ======================================== --
- function sendPackage(message)
- if modem ~= nil then
- modem.broadcast(PORT, message)
- end
- end
- -- ================================================= M A I N ================================================= --
- if glass ~= nil then glass.clear() end
- if modem ~= nil then modem.open(PORT) end
- userlist = readList('userlist.txt')
- doorlist = readList('doorlist.txt')
- history = {}
- infout("Нажмите любую кнопку, чтобы перейти в режим ввода команд.")
- -- Главный цикл - обновление/обработка --
- while true do
- -- ждем событие
- name, add, a, b, c, d = event.pull(OPEN_TIME+0.2)
- -- чистим очки
- if glass_uptime ~= 0 then
- if (comp.uptime() - glass_uptime) > GLASS_TIME then
- glass_clear()
- glass_uptime = 0
- end
- end
- -- закрываем двери
- for a,b in pairs(doorlist) do
- if b.time ~= nil then
- if (comp.uptime() - b.time) > OPEN_TIME then
- open(a, true)
- b.time = nil
- end
- end
- end
- -- обработка пользовательских команд с терминала и очков
- if name == 'key_down' then
- term.write("\n>> ")
- command = term.read(history)
- if not process(command, true) then break end
- elseif name == 'chat_command' then
- if not process(add, false) then break end
- -- обработка "звонков в двери"
- elseif name == 'touch' then
- if contains(doorlist, add) then
- -- выводим информацию
- print("\n"..d.." у "..doorlist[add].name.." ("..string.sub(add, 1, 4)..")!")
- -- отчет для лога
- local date = os.date()
- log_message = date..' / '..d..' / '..doorlist[add].name.." ("..string.sub(add, 1, 4)..") | "
- net_message = {date = date, player = d, door = doorlist[add].name, address = add}
- -- проверка по списку
- if not contains(userlist, d) then
- glass_splash(log_message..'?', 1)
- show(add, WAIT)
- warnout("В списке его нет. Что делать?")
- toLog(log_message..'?')
- last_door = add
- net_message.message = '?'
- sendPackage(serial.serialize(net_message))
- else
- if doorlist[add].level > userlist[d] then
- glass_splash(log_message..'X', 2)
- show(add, DENY)
- print("В доступе отказано!")
- toLog(log_message..'X')
- net_message.message = 'X'
- sendPackage(serial.serialize(net_message))
- else
- glass_splash(log_message..'Y', 0)
- open(add)
- print("Доступ разрешен.")
- toLog(log_message..'Y')
- net_message.message = 'Y'
- sendPackage(serial.serialize(net_message))
- end
- end
- end
- -- обрабатывает сообщения по сети
- elseif name == 'modem_message' then
- local data = serial.unserialize(d)
- if data.command == 'open' then
- trytoopen(data.address)
- end
- end
- end
- -- завершение (сохраняем списки, чистим экран)
- if modem ~= nil then modem.close(PORT) end
- saveList(userlist, 'userlist.txt')
- saveList(doorlist, 'doorlist.txt')
- term.clear()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement