MineOS/lib/modemConnection.lua

294 lines
9.9 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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