Новая либа для графонистой работы с модемами

This commit is contained in:
Igor 2016-03-01 22:52:41 +03:00
parent aac9884dd0
commit d7ae5cd2e4

View File

@ -0,0 +1,293 @@
local event = require("event")
local computer = require("computer")
local component = require("component")
local serialization = require("serialization")
local unicode = require("unicode")
local ecs, image
local modem = component.modem
local gpu = component.gpu
local wirelessConnection = {}
----------------------------------------------------------------------------------------------------------------------------------
local infoMessages = {
userTriesToConnectNoGUI = "Пользователь %s желает установить с вами соединение. Разрешить?",
noModem = "Этой библиотеке требуется сетевая карта для работы",
}
wirelessConnection.port = 322
wirelessConnection.sendingDataDelay = 1.0
wirelessConnection.receiveMessagesFromRobots = true
----------------------------------------------------------------------------------------------------------------------------------
local xSize, ySize = gpu.getResolution()
local computerIcon
if not component.isAvailable("robot") then
image = require("image")
ecs = require("ECSAPI")
computerIcon = image.load("MineOS/System/OS/Icons/Script.pic")
end
----------------------------------------------------------------------------------------------------------------------------------
local obj = {}
local function newObj(class, name, ...)
obj[class] = obj[class] or {}
obj[class][name] = {...}
end
local function askForConnection(userData)
local data = ecs.universalWindow("auto", "auto", 36, 0x262626, true,
{"EmptyLine"},
{"CenterText", ecs.colors.orange, "WirelessConnection"},
{"EmptyLine"},
{"CenterText", 0xffffff, "Пользователь " .. ecs.stringLimit("end", userData.address, 6) .. " желает" },
{"CenterText", 0xffffff, "установить с вами беспроводное соединение." },
{"EmptyLine"},
{"CenterText", 0xffffff, "Разрешить подключение?" },
{"EmptyLine"},
{"Button", {ecs.colors.orange, 0x262626, "Да"}, {0x999999, 0xffffff, "Нет"}}
)
end
local function modemMessageHandler(_, localAddress, remoteAddress, port, distance, ...)
local messages = {...}
if #messages > 0 then
if port == wirelessConnection.port then
if messages[1] == "requestingPermissionToConnect" then
askForConnection(messages[2])
elseif messages[1] == "iAmHereAddMePlease" then
if not wirelessConnection.availableUsers[remoteAddress] then
local userData = serialization.unserialize(messages[2])
if not userData.isRobot or (userData.isRobot and wirelessConnection.receiveMessagesFromRobots) then
wirelessConnection.availableUsers[userData.address] = userData
modem.send(remoteAddress, wirelessConnection.port, "iAmHereAddMePlease", wirelessConnection.dataToSend)
computer.pushSignal("userlistChanged")
end
end
elseif messages[1] == "iAmDisconnecting" then
if wirelessConnection.availableUsers[remoteAddress] then
wirelessConnection.availableUsers[remoteAddress] = nil
computer.pushSignal("userlistChanged")
end
end
end
end
end
local function createSendingArray()
wirelessConnection.dataToSend = {}
wirelessConnection.dataToSend.address = wirelessConnection.localAddress
wirelessConnection.dataToSend.name = component.filesystem.getLabel()
if component.isAvailable("robot") then
wirelessConnection.dataToSend.isRobot = true
if component.isAvailable("inventory_controller") then
wirelessConnection.dataToSend.inventoryController = true
end
if component.isAvailable("tank_controller") then
wirelessConnection.dataToSend.tankController = true
end
if component.isAvailable("crafting") then
wirelessConnection.dataToSend.crafting = true
end
if component.isAvailable("redstone") then
wirelessConnection.dataToSend.redstone = true
end
end
wirelessConnection.dataToSend = serialization.serialize(wirelessConnection.dataToSend)
end
--Нарисовать окружность, алгоритм спизжен с вики
local function circle(xCenter, yCenter, radius, color)
gpu.setBackground(color)
local function insertPoints(x, y)
gpu.set(xCenter + x * 2, yCenter + y, " ")
gpu.set(xCenter + x * 2, yCenter - y, " ")
gpu.set(xCenter - x * 2, yCenter + y, " ")
gpu.set(xCenter - x * 2, yCenter - y, " ")
gpu.set(xCenter + x * 2 + 1, yCenter + y, " ")
gpu.set(xCenter + x * 2 + 1, yCenter - y, " ")
gpu.set(xCenter - x * 2 + 1, yCenter + y, " ")
gpu.set(xCenter - x * 2 + 1, yCenter - y, " ")
end
local x = 0
local y = radius
local delta = 3 - 2 * radius;
while (x < y) do
insertPoints(x, y);
insertPoints(y, x);
if (delta < 0) then
delta = delta + (4 * x + 6)
else
delta = delta + (4 * (x - y) + 10)
y = y - 1
end
x = x + 1
end
if x == y then insertPoints(x, y) end
end
local function drawCircles(xCircle, yCircle, minumumRadius, maximumRadius, step, currentRadius)
for radius = minumumRadius, maximumRadius, step do
if radius == currentRadius then
circle(xCircle, yCircle, radius, 0xAAAAAA)
else
circle(xCircle, yCircle, radius, 0xDDDDDD)
end
end
end
local function drawIconAndAddress(x, y, background, foreground, text)
image.draw(x + 3, y, computerIcon)
ecs.colorTextWithBack(x, y + 5, foreground, background, ecs.stringLimit("end", text, 14))
return x, y, x + 13, y + 5
end
local function drawHorizontalIcons()
local height = 8
local y = math.floor(ySize / 2 - height / 2)
local background = 0x66A8FF
ecs.square(1, y, xSize, height, background)
local iconWidth = 14
local spaceBetween = 2
local totalWidth = ecs.getArraySize(wirelessConnection.availableUsers) * (iconWidth + spaceBetween) - spaceBetween
local x = math.floor(xSize / 2 - totalWidth / 2) + 1
obj.Users = {}
local counter = 0
local limit = math.floor(xSize / (iconWidth + spaceBetween))
y = y + 1
for address in pairs(wirelessConnection.availableUsers) do
if counter < limit then
newObj("Users", address, drawIconAndAddress(x, y, background, 0xFFFFFF, address))
end
x = x + iconWidth + spaceBetween
counter = counter + 1
end
end
local function drawSelectedIcon(x, y, background, foreground, text)
local selectionWidth = 16
local oldPixels = ecs.rememberOldPixels(x - 1, y, x + selectionWidth - 2, y + 13)
ecs.square(x - 1, y, selectionWidth, 8, background)
drawIconAndAddress(x, y + 1, background, foreground, text)
obj.CykaKnopkaInfo = { ecs.drawButton(x - 1, y + 8, selectionWidth, 3, "Информация", 0xff6699, 0xFFFFFF) }
obj.CykaKnopkaConnect = { ecs.drawButton(x - 1, y + 11, selectionWidth, 3, "Подключиться", 0xff3333, 0xFFFFFF) }
return oldPixels
end
local function connectionGUI()
ecs.square(1, 1, xSize, ySize, 0xEEEEEE)
local xCircle, yCircle = math.floor(xSize / 2), ySize - 3
local minumumRadius, maximumRadius = 7, xCircle * 0.8
local step = 4
local currentRadius = minumumRadius
drawIconAndAddress(xCircle - 6, ySize - 6, 0xEEEEEE, 0x262626, wirelessConnection.localAddress)
while true do
if ecs.getArraySize(wirelessConnection.availableUsers) > 0 then
currentRadius = 0
drawCircles(xCircle, yCircle, minumumRadius, maximumRadius, step, currentRadius)
drawHorizontalIcons()
local oldPixels, needToUpdate
while true do
if not oldPixels and needToUpdate then
if ecs.getArraySize(wirelessConnection.availableUsers) <= 0 then
ecs.square(1, 1, xSize, ySize, 0xEEEEEE)
drawIconAndAddress(xCircle - 6, ySize - 6, 0xEEEEEE, 0x262626, wirelessConnection.localAddress)
currentRadius = minumumRadius
break
else
drawHorizontalIcons()
needToUpdate = false
end
end
local e = { event.pull() }
if e[1] == "touch" then
if oldPixels then ecs.drawOldPixels(oldPixels); oldPixels = nil end
for address in pairs(obj.Users) do
if ecs.clickedAtArea(e[3], e[4], obj.Users[address][1], obj.Users[address][2], obj.Users[address][3], obj.Users[address][4]) then
oldPixels = drawSelectedIcon(obj.Users[address][1], obj.Users[address][2] - 1, 0xCCCCFF, 0x262626, address)
break
end
end
elseif e[1] == "userlistChanged" then
needToUpdate = true
end
end
else
drawCircles(xCircle, yCircle, minumumRadius, maximumRadius, step, currentRadius)
currentRadius = currentRadius + step
if currentRadius > (maximumRadius + step) then currentRadius = minumumRadius end
os.sleep(0)
end
end
end
----------------------------------------------------------------------------------------------------------------------------------
function wirelessConnection.stopReceivingData()
event.ignore("modem_message", modemMessageHandler)
end
function wirelessConnection.startReceivingData()
wirelessConnection.stopReceivingData()
event.listen("modem_message", modemMessageHandler)
end
function wirelessConnection.disconnect()
modem.broadcast(wirelessConnection.port, "iAmDisconnecting")
end
function wirelessConnection.sendPersonalData()
wirelessConnection.disconnect()
modem.broadcast(wirelessConnection.port, "iAmHereAddMePlease", wirelessConnection.dataToSend)
end
function wirelessConnection.changePort(newPort)
modem.close(wirelessConnection.port)
modem.open(newPort)
wirelessConnection.port = newPort
wirelessConnection.remoteAddress = nil
wirelessConnection.localAddress = component.getPrimary("modem").address
wirelessConnection.availableUsers = {}
createSendingArray()
end
function wirelessConnection.connect()
wirelessConnection.sendPersonalData()
connectionGUI()
end
function wirelessConnection.init()
if component.isAvailable("modem") then
wirelessConnection.changePort(wirelessConnection.port)
wirelessConnection.startReceivingData()
else
ecs.error(infoMessages.noModem)
return
end
end
----------------------------------------------------------------------------------------------------------------------------------
wirelessConnection.init()
wirelessConnection.sendPersonalData()
-- wirelessConnection.connect()
----------------------------------------------------------------------------------------------------------------------------------
return wirelessConnection