Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Utils library v0.3 by DrPepper
- --
- --
- -------------------------------------------------------------------
- local Widgets = require("widgets_0_3")
- -------------------------------------------------------------------
- -- Tries to read table from the file
- -- Returns table or (nil, error message)
- function ReadTableFromFile(filename)
- local resTable
- local f = fs.open(filename, "r")
- if f then
- local fstr = f.readAll()
- f.close()
- if fstr then
- local resTable = textutils.unserialize(fstr)
- if resTable then
- return resTable
- else
- return nil, "Can't unserialize "..filename
- end
- else
- return nil, "Can't read "..filename
- end
- else
- return nil, "Can't open "..filename
- end
- end
- -------------------------------------------------------------------
- -- Tries to write table to the file
- -- Returns true or (nil, error message)
- function WriteTableToFile(t, filename)
- local f = fs.open(filename, "w")
- if f then
- local resString = textutils.serialize(t)
- if resString then
- f.write(resString)
- f.close()
- return true
- else
- return nil, "Can't serialize "..filename
- end
- else
- return nil, "Can't open "..filename
- end
- end
- -------------------------------------------------------------------
- -- Wraps text, returns an array of strings, respects line endings
- function string:wrap(len)
- if len < 1 then len=#self end
- local strings = {}
- for line in self:gmatch("([^\n]+)") do
- while #line > 0 do
- table.insert(strings, line:sub(1, len))
- line = line:sub(len+1)
- end
- end
- return strings
- end
- -------------------------------------------------------------------
- -- Backport of the same function from newer CC:Tweaked
- -- Colour to hex lookup table for toBlit
- local color_hex_lookup = {}
- for i = 0, 15 do
- color_hex_lookup[2 ^ i] = string.format("%x", i)
- end
- local function colorToBlit(color)
- local hex = color_hex_lookup[color]
- if hex then return hex end
- if color < 0 or color > 0xffff then error("Colour out of range", 2) end
- return string.format("%x", math.floor(math.log(color, 2)))
- end
- -------------------------------------------------------------------
- -- For given key-value table returns an indexed array of strings
- -- ready for output and a table of index-key pairs.
- local function ConvertTableToArrayStrings(t)
- local arr, ind = {}, {}
- for k, v in pairs(t) do
- if type(v)=="table" then
- local s = ""
- for kk, vv in pairs(v) do
- if type(kk)=="number" then kk = ""
- else kk = tostring(kk).."="
- end
- s = s..kk..tostring(vv).."; "
- end
- v=s
- end
- table.insert(arr, string.format("%s: %s", k, tostring(v)))
- table.insert(ind, #arr, k)
- end
- return arr, ind
- end
- -------------------------------------------------------------------
- -- Same as above but with textutils.serialize()
- local function ConvertTableToArraySerialize(t)
- local TS = textutils.serialize
- local arr, ind = {}, {}
- for k, v in pairs(t) do
- if type(v)=="table" then
- local s = ""
- for kk, vv in pairs(v) do
- if type(kk)=="number" then kk = ""
- else kk = TS(kk).."="
- end
- s = s..kk..TS(vv).."; "
- end
- table.insert(arr, string.format("%s: %s", TS(k), s))
- else
- table.insert(arr, string.format("%s: %s", TS(k), TS(v)))
- end
- table.insert(ind, #arr, k)
- end
- return arr, ind
- end
- -------------------------------------------------------------------
- -- Peripheral manager
- -- Contains peripherals table with names of every peripheral
- -- currently connected or saved in peripheral.cfg with its state:
- -- peripherals = {peripheral_name = { wrapped = {table},
- -- widgets = {array}, callable = true, lastUpdated = epoch,
- -- lg="GRP1", lgm = true, pos = nil or {x, y, z}, eu = 3000,
- -- euMax = 10000, type = warpdriveLaser } }
- -- Contains laser group table with names of each laser peripheral
- -- and lock state (nil means unlocked, number means targeter id that
- -- locked the group):
- -- laserGroups = {GRP1 = {main = "laser3", aux = {"laser1",
- -- "laser2", ...}, lock = 2}}
- local function CreatePeripheralManager()
- local self = { peripherals = {},
- updaterPeriod = 1, -- seconds
- peripheralPeriod = 2000, -- ms
- logger = nil, -- optional external logger
- widgetsToUpdate = {}, -- widgets to call :draw() on after each update cycle
- laserGroups = {}, --
- freq = 30000, -- laser freq
- scRedThr = 0.1, -- fraction of max energy below which the status is red
- scOrangeThr = 0.9 -- fraction of max energy below which the status is red
- }
- --forward declarations
- local function connectPeripheral(side) end
- local function fillLaserGroups() end
- local function updatePeripheral(side) end
- local function ReadPeripheralTable() end
- local function SetStatusLaser(p) end
- local function init(initLasers)
- --try reading the config into peripherals table
- local res = ReadPeripheralTable(self.peripherals)
- if initLasers then fillLaserGroups() end
- --connect all peripherals
- local connected = peripheral.getNames()
- for _,v in ipairs(connected) do
- connectPeripheral(v)
- end
- end
- -- populates laser group table with data from peripheral table
- fillLaserGroups = function()
- for name, p in pairs(self.peripherals) do
- if p.lg then
- if not self.laserGroups[p.lg] then
- self.laserGroups[p.lg] = {aux = {} }
- end
- if p.lgm then -- peripheral marked as main laser
- if self.laserGroups[p.lg].main and self.logger then
- self.logger.log("ERROR",
- string.format("Two main lasers %s and %s in %s",
- self.laserGroups[p.lg].main, name, p.lg),
- "PeripheralManager")
- end
- self.laserGroups[p.lg].main = name
- else
- table.insert(self.laserGroups[p.lg].aux, name)
- end
- end
- end
- end
- -- update the in-mem table with connected peripheral
- connectPeripheral = function (side)
- if not self.peripherals[side] then self.peripherals[side] = {} end
- cp = self.peripherals[side]
- cp.wrapped = peripheral.wrap(side)
- cp.type = peripheral.getType(side)
- updatePeripheral(side)
- if cp.widgets then
- for i,w in ipairs(cp.widgets) do w:draw() end
- end
- end
- -- mark peripheral as disconnected
- local function disconnectPeripheral(side)
- local dp = self.peripherals[side]
- if not dp then return end
- dp.wrapped = nil
- dp.callable = false
- if dp.widgets then
- for i,w in ipairs(cp.widgets) do w:draw() end
- end
- end
- -- update peripheral
- updatePeripheral = function (side)
- local now = os.epoch("utc")
- local p = self.peripherals[side]
- if not p then return end
- if not p.wrapped then
- if peripheral.isPresent(side) then connectPeripheral(side)
- else return
- end
- end
- if p.wrapped.isInterfaced then
- p.callable = p.wrapped.isInterfaced()
- else
- p.callable = true
- end
- if p.callable then
- --Energy
- if p.wrapped.getEnergyStatus then
- p.eu, p.euMax = p.wrapped.getEnergyStatus()
- end
- --Position
- if p.wrapped.getLocalPosition and not p.pos then
- p.pos = table.pack(p.wrapped.getLocalPosition())
- end
- end
- --laser-specific stuff
- if p.type and p.type == "warpdriveLaser" then
- if not p.frequency or p.frequency ~= self.freq then
- if p.wrapped and p.wrapped.beamFrequency and p.callable then
- p.frequency = p.wrapped.beamFrequency(self.freq)
- if not p.frequency or p.frequency == -1 then
- self.logger.log("ERROR", "freq == -1", "updatePeripheral")
- end
- end
- end
- SetStatusLaser(p)
- end
- --TODO further updates here
- p.lastUpdated = os.epoch("utc")
- end
- -- coroutine to process peripheral events
- local function managerCoroutine()
- while true do
- local p1, p2, p3, p4, p5 = os.pullEvent()
- if p1 == "peripheral" then
- connectPeripheral(p2)
- elseif p1 == "peripheral_detach" then
- disconnectPeripheral(p2)
- end
- end
- end
- local function updaterCoroutine()
- local tid = os.startTimer(self.updaterPeriod)
- while true do
- local p1, p2--[[, p3, p4, p5--]] = os.pullEvent()
- if (p1 == "timer" and p2 == tid)
- or p1 == "updatePeripheralsNow" then
- local sMs = os.epoch("utc")
- for name, per in pairs(self.peripherals) do
- if os.epoch("utc") > (sMs + 40) then break end
- if not per.lastUpdated
- or sMs >= per.lastUpdated + self.peripheralPeriod then
- updatePeripheral(name)
- end
- end
- local uMs = os.epoch("utc")
- if self.widgetsToUpdate then
- for i,w in ipairs(self.widgetsToUpdate) do w:draw() end
- end
- local dMs = os.epoch("utc")
- if self.logger then
- self.logger.log("PERF",
- "Took "..(uMs - sMs).."ms to update, "..(dMs - uMs)
- .."ms to redraw", "updaterCoroutine")
- end
- tid = os.startTimer(self.updaterPeriod)
- end
- end
- end
- local function setLogger(logger)
- self.logger = logger
- end
- --loads table deserialized from peripheral.cfg into t
- ReadPeripheralTable = function(t)
- --try reading the config into peripherals table
- local res, err = ReadTableFromFile("peripheral.cfg")
- if not res and self.logger then
- self.logger.log("ERROR", err, "ReadPeripheralTable")
- return nil
- end
- --copy data from it
- if res then
- for k,v in pairs(res) do
- t[k] = v
- end
- end
- return true
- end
- -- rewrites peripheral.cfg with the supplied table
- local WritePeripheralTable = function(t)
- local res, err = WriteTableToFile(t, "peripheral.cfg")
- if not res and self.logger then
- self.logger.log("ERROR", err, "WritePeripheralTable")
- return nil
- end
- return true
- end
- -- assigns a color representing the status
- SetStatusLaser = function (perTableEntry)
- if perTableEntry.wrapped and perTableEntry.callable
- and perTableEntry.eu and perTableEntry.euMax
- and perTableEntry.pos then
- local en = perTableEntry.eu / perTableEntry.euMax
- if en < self.scRedThr or perTableEntry.eu == 0 then
- perTableEntry.sc = colors.red
- elseif en < self.scOrangeThr then
- perTableEntry.sc = colors.orange
- else
- perTableEntry.sc = colors.green
- end
- else
- perTableEntry.sc = colors.gray
- end
- end
- local function GetDefaultParamsByType(perType)
- if perType == "warpdriveLaser" then
- return {lg = "LG", lgm = false, offset = {0,-1.5,0}}
- --for bottom main emitter position
- --return {lg = "LG", lgm = false, offset = {0,-1.5,0}}
- --for top main emitter position
- --return {lg = "LG", lgm = false, offset = {0,1.5,0}}
- else
- return {}
- end
- end
- -- Returns first found peripheral of given type from
- -- self.peripherals (might not be wrapped) with "param" = val if
- -- val is defined, with "param" if val is nil, or returns nil
- local function GetPeripheralByParamAndType(param, val, type)
- for _, p in pairs(self.peripherals) do
- if p.type and p.type == type then
- if p[param] and (val == nil or p[param] == val) then
- return p
- end
- end
- end
- end
- return {
- ManagerCoroutine = managerCoroutine,
- UpdaterCoroutine = updaterCoroutine,
- peripherals = self.peripherals,
- SetLogger = setLogger,
- widgetsToUpdate = self.widgetsToUpdate,
- Init = init,
- laserGroups = self.laserGroups,
- ReadPeripheralTable = ReadPeripheralTable,
- WritePeripheralTable = WritePeripheralTable,
- GetDefaultParamsByType = GetDefaultParamsByType,
- GetPeripheralByParamAndType = GetPeripheralByParamAndType
- }
- end
- local PeripheralManager = CreatePeripheralManager()
- -------------------------------------------------------------------
- -- Basic targeter
- -- has local array of laser groups copied from the PeripheralManager
- -- [1] = {name="LG1", p={mainRef, aux1ref, aux2ref, ...},
- -- canHit = {true, false, nil, ...}}}
- local function CreateTargeter(targeterId, logger)
- local self = {
- manager = PeripheralManager,
- isFiring = false,
- isAborted = false,
- id = targeterId, -- to identify fire requests and lock lasers
- logger = logger,
- target = {nil, nil, nil}, --currently assigned target
- groups = {},
- selected = {}, --indices from groups array, "selected" means true,
- --"not selected" means nil
- modeBoost = true,
- attemptsMax = 30, --tries to find a group to fire
- minDstSq = 900, --won't shoot closer than this (squared)
- repeats = 3, --times to fire in succession
- repeatDelay = 1.0, --delay between repeats in seconds
- statusWidgetRef = nil, --has to have .text, .textColor and :draw()
- TargeterCoroutine = function() end,
- DisplayGroup = function() end,
- IsTargetAllowed = function() end,
- OnGroupSelect = function() end,
- SetTarget = function() end,
- GetTarget = function() end,
- ModeBoost = function() end,
- SetStatusWidget = function() end,
- FiringSequence = function() end,
- UpdateStatus = function() end
- }
- -- getter/setter
- self.ModeBoost = function (val)
- if val == nil then
- return self.modeBoost
- else
- if val == true then self.modeBoost = true return end
- if val == false then self.modeBoost = false return end
- end
- end
- self.SetStatusWidget = function(ref)
- self.statusWidgetRef = ref
- end
- -- updates status message (have to set the widget first)
- -- textColor is optional
- self.UpdateStatus = function(msg, textColor)
- if not self.statusWidgetRef or not self.statusWidgetRef.text
- or not self.statusWidgetRef.draw then return end
- self.statusWidgetRef.text = msg
- if textColor and self.statusWidgetRef.textColor then
- self.statusWidgetRef.textColor = textColor
- end
- self.statusWidgetRef:draw()
- end
- -- fills laser group array
- local function fillGroups()
- self.groups = {}
- for n, g in pairs(self.manager.laserGroups) do
- tgr = {name = n, p = {}, canHit = {}}
- if g.main and self.manager.peripherals[g.main] then
- tgr.p[1] = self.manager.peripherals[g.main]
- if g.aux then
- for _, auxName in ipairs(g.aux) do
- auxRef = self.manager.peripherals[auxName]
- if auxRef then tgr.p[#tgr.p+1] = auxRef end
- end
- end
- self.groups[#self.groups+1] = tgr
- else
- if self.logger then
- self.logger.log("ERROR", "No main laser in "..n, "fillGroups")
- end
- end
- end
- --TODO optional sorting
- end
- self.GetTarget = function()
- return self.target[1], self.target[2], self.target[3]
- end
- --Sets new target, updates canHit values for each group
- self.SetTarget = function(x, y, z)
- self.target[1], self.target[2], self.target[3] = x, y, z
- self.logger.log("DEBUG", string.format("Set %s,%s,%s", x, y, z),
- "setTarget")
- for i_g, g in ipairs(self.groups) do
- for i_l, l in ipairs(g.p) do
- local res = nil
- if l and l.pos then --laser and its position are ok
- local relCoords = table.pack(x - l.pos[1],
- y - l.pos[2],
- z - l.pos[3])
- -- TODO distance check here
- res = self.IsTargetAllowed(l, relCoords)
- end
- g.canHit[i_l] = res
- end
- end
- end
- --blits laser group through the supplied widget (designed for list)
- --cuts group name after 4 symbols
- self.DisplayGroup = function(w, index, length, isSelected)
- --NWU1ooooo____ --like this
- local textColor = colorToBlit(colors.white)
- local bgColor = colorToBlit(colors.blue)
- if isSelected then bgColor = colorToBlit(colors.cyan) end
- local group = self.groups[index]
- if not group or not group.name then
- if self.logger then
- self.logger.log("ERROR", "No group #"..index, "DisplayGroup")
- end
- return
- end
- --group in the manager
- local managerGroup = self.manager.laserGroups[group.name]
- if not managerGroup then
- self.logger.log("ERROR",
- "No group "..tostring(group.name).." in the manager",
- "CheckFireGroup")
- elseif managerGroup.lock then
- if managerGroup.lock ~= self.id then
- textColor = colorToBlit(colors.gray) --locked by other
- else
- textColor = colorToBlit(colors.yellow) --locked by self
- end
- end
- --group name blit
- local str=string.format("%-4.4s", group.name)
- local col=textColor:rep(4)
- local bg=bgColor:rep(4)
- --lasers
- for i_p = 1, length-4 do
- if group.p[i_p] then
- --symbol
- if i_p == 1 then
- str = str.."\4"
- else
- str = str.."\7"
- end
- --status
- if group.p[i_p].sc then
- col = col..colorToBlit(group.p[i_p].sc)
- else
- col = col..colorToBlit(colors.gray)
- end
- --bg
- if group.canHit[i_p] then
- bg = bg..colorToBlit(colors.green)
- else
- bg = bg..bgColor
- end
- else
- str = str.." "
- col = col..colorToBlit(colors.black)
- bg = bg..bgColor
- end
- end
- if not w or not w.window then
- if self.logger then
- self.logger.log("ERROR", "Widget error", "displayGroup")
- end
- return
- end
- w.window.blit(str, col, bg)
- end
- -- overload for WidgetListView:OnSelect()
- self.OnGroupSelect = function (w)
- if not w then return end
- for i_g, g in ipairs(self.groups) do
- local mg = self.manager.laserGroups[g.name]
- if not mg then
- self.logger.log("ERROR", "No group "..tostring(g.name)
- .." in the manager", "CheckFireGroup")
- return
- end
- if not mg.lock or mg.lock == self.id then
- if not w.selected then --no widget selection data
- if self.selected[i_g] then
- mg.lock = nil
- self.selected[i_g] = nil
- self.logger.log("DEBUG", "unlocked "..g.name, "OGS")
- end
- else
- if w.selected[i_g] then --selected in the widget
- mg.lock = self.id
- self.selected[i_g] = true
- self.logger.log("DEBUG", "locked "..g.name, "OGS")
- else --not selected in the widget (nil or false)
- mg.lock = nil
- self.selected[i_g] = nil
- self.logger.log("DEBUG", "unlocked "..g.name, "OGS")
- end
- end
- end
- end
- if not w.selected then
- self.selected = {}
- end
- end
- -- input: ref to laser peripheral, relative {x,y,z} of the target
- self.IsTargetAllowed = function(laserPerRef, relXyzT)
- --TODO sanity checks
- local x, y, z = table.unpack(relXyzT)
- self.logger.log("DEBUG", string.format("%s,%s,%s",
- x, y, z ), "IsTargetAllowed")
- if x*x + y*y + z*z < self.minDstSq then
- self.logger.log("DEBUG", "Too close", "IsTargetAllowed")
- return false
- end
- ax, ay, az = math.abs(x), math.abs(y), math.abs(z)
- if laserPerRef.N and z < 0 and az >= ax and az >= ay then
- self.logger.log("DEBUG", "N", "IsTargetAllowed")
- return true
- end
- if laserPerRef.S and z > 0 and az >= ax and az >= ay then
- self.logger.log("DEBUG", "S", "IsTargetAllowed")
- return true
- end
- if laserPerRef.W and x < 0 and ax >= ay and ax >= az then
- self.logger.log("DEBUG", "W", "IsTargetAllowed")
- return true
- end
- if laserPerRef.E and x > 0 and ax >= ay and ax >= az then
- self.logger.log("DEBUG", "E", "IsTargetAllowed")
- return true
- end
- if laserPerRef.D and y < 0 and ay >= ax and ay >= az then
- self.logger.log("DEBUG", "D", "IsTargetAllowed")
- return true
- end
- if laserPerRef.U and y > 0 and ay >= ax and ay >= az then
- self.logger.log("DEBUG", "U", "IsTargetAllowed")
- return true
- end
- self.logger.log("DEBUG", "false", "IsTargetAllowed")
- return false
- end
- -- simple fire condition function to fire once
- local function CheckFireCondition()
- if not self.target[1] or not self.target[2]
- or not self.target[3] then
- self.UpdateStatus("NO TARG", colors.red)
- return false
- end
- if self.isAborted then
- self.UpdateStatus("ABORTED", colors.red)
- return false
- end
- return true --TODO
- end
- -- returns true if the laser is ready to fire sans direction check
- local function CheckLaser(laserPerRef)
- if not laserPerRef.sc then return false end
- return laserPerRef.sc == colors.green
- end
- -- returns true if the entire laser group is ready to fire
- -- in boosted mode, or at least one laser is ready otherwise.
- -- Checks if the group is locked to the current targeter or no
- -- groups are locked to it at all
- -- Locks the group
- local function CheckFireGroup(g)
- -- lock check
- local groupM = self.manager.laserGroups[g.name]
- if not groupM then
- self.logger.log("ERROR",
- "No group "..tostring(g.name).." in the manager",
- "CheckFireGroup")
- return false
- end
- --locked by some other targeter
- if groupM.lock and groupM.lock ~= self.id then
- self.logger.log("DEBUG",g.name.." locked by othr","CheckFG")
- return false
- end
- --some groups are selected (self.selected not empty),
- --but this one does not have a lock
- if self.selected and next(self.selected) ~= nil
- and not groupM.lock then
- return false
- end
- -- direction check
- if self.ModeBoost then
- if not g.canHit[1] then
- self.logger.log("DEBUG",g.name.." can't hit","CheckFG")
- return false
- end
- -- individual laser check
- for i_l=1, #g.p do
- if not CheckLaser(g.p[i_l]) then
- self.logger.log("DEBUG",g.name.." has false on laser "..
- tostring(i_l),"CheckFG")
- return false
- end
- end
- else --at least one can hit
- for i_l=1, #g.p do
- if g.canHit[i_l] and CheckLaser(g.p[i_l]) then
- break
- end
- end
- end
- -- locking to self
- groupM.lock = self.id
- return true
- end
- -- returns an array of suitable laser groups ready to fire
- -- this one tries attemptsMax times to find a single group with 1s
- -- cooldown if none are available
- local function GetSuitableGroups()
- for attempt = 1, self.attemptsMax do
- if not CheckFireCondition() then
- return {}
- end
- for i_g, g in ipairs(self.groups) do
- if CheckFireGroup(g)==true then return {g} end
- end
- self.UpdateStatus("WAIT #"..attempt, colors.orange)
- sleep(1)
- end
- self.UpdateStatus("NO GROUPS", colors.red)
- return {}
- end
- --returns number of groups which opened fire successfully
- local function FireBoost(groupsArray)
- local fired = 0
- for _,g in ipairs(groupsArray) do
- local xm, ym, zm = table.unpack(g.p[1].pos)
- local xt, yt, zt = table.unpack(self.target)
- for i_l=2, #g.p do
- local xo, yo, zo = 0, 0, 0
- if g.p[i_l].offset then
- xo, yo, zo = table.unpack(g.p[i_l].offset)
- end
- --TODO check if callable
- local xl, yl, zl = table.unpack(g.p[i_l].pos)
- g.p[i_l].wrapped.emitBeam(xm-xl+xo, ym-yl+yo, zm-zl+zo)
- --mark lasers red
- g.p[i_l].sc = colors.red
- self.logger.log("DEBUG", string.format("%s[%s].emitBeam(%s,%s,%s)",
- g.name, i_l, xm-xl+xo, ym-yl+yo, zm-zl+zo), "FireBoost")
- end
- sleep(0.1) --boost sleep
- if not CheckFireCondition() then
- return fired
- end
- g.p[1].wrapped.emitBeam(xt-xm, yt-ym, zt-zm)
- --mark lasers red
- g.p[1].sc = colors.red
- self.logger.log("DEBUG", string.format("%s[1].emitBeam(%s,%s,%s)",
- g.name, xt-xm, yt-ym, zt-zm), "FireBoost")
- fired = fired+1
- --UpdateStatus("FIRED".."".."B", colors.green)
- end
- return fired
- end
- --TODO
- local function FireAll(groupsArray)
- local count = 0
- for _,g in ipairs(groupsArray) do
- local xt, yt, zt = table.unpack(self.target)
- for i_l=1, #g.p do
- if g.canHit[i_l] and CheckLaser(g.p[i_l]) then
- local xl, yl, zl = table.unpack(g.p[i_l].pos)
- g.p[i_l].wrapped.emitBeam(xt-xl, yt-yl, zt-zl)
- count = count+1
- end
- end
- end
- self.UpdateStatus("FIRED #"..count, colors.green)
- end
- --unlocks every group except selected
- local function UnlockGroups()
- for i_g, g in ipairs(self.groups) do
- local mg = self.manager.laserGroups[g.name]
- if not mg then
- self.logger.log("ERROR", "No group "..tostring(g.name)
- .." in the manager", "UnlockGroups")
- return
- end
- if not self.selected then
- self.logger.log("ERROR", "nil", "UG")
- return
- end
- if mg.lock and mg.lock == self.id then
- if not self.selected[i_g] then
- mg.lock = nil
- self.logger.log("DEBUG", "unlocked "..g.name, "UG")
- end
- end
- end
- end
- self.FiringSequence = function()
- self.isFiring = true
- for i_r=1, self.repeats do
- if CheckFireCondition() then
- --find suitable laser groups
- local groupsArray = GetSuitableGroups()
- if self.modeBoost then
- FireBoost(groupsArray)
- self.UpdateStatus("FIRED #"..i_r, colors.green)
- else
- FireAll(groupsArray)
- end
- --unlock laser groups
- UnlockGroups(groupsArray)
- else
- break
- end
- if i_r < self.repeats then sleep(self.repeatDelay) end
- end
- self.isFiring = false
- end
- self.TargeterCoroutine = function()
- self.UpdateStatus("STARTED", colors.green)
- while true do
- local p1, p2, p3, p4, p5 = os.pullEvent()
- if p1 == "fire" and p2 == self.id then
- self.logger.log("DEBUG", "fire event: id="..tostring(p2), "TC")
- self.FiringSequence()
- --UpdateStatus("STANDBY", colors.green)
- end
- end
- end
- fillGroups()
- return self
- end
- -- Repeating targeter --now included in the basic
- --local function CreateTargeterR(targeterId, logger)
- -- local self = table.pack(CreateTargeter(targeterId, logger))
- -- basicFireSequence = self.FiringSequence()
- --end
- -- Automatic targeter (to work with laser cameras)
- local function CreateTargeterAutoCam(targeterId, logger)
- local self = CreateTargeter(targeterId, logger)
- self.TargeterCoroutine = function()
- self.UpdateStatus("LISTEN", colors.green)
- while true do
- local p1, p2, p3, p4, p5 = os.pullEvent()
- self.logger.log("DEBUG", tostring(p1)..","..
- tostring(p2)..","..tostring(p3).."...", "ACAM")
- self.UpdateStatus(p1, colors.pink)
- end
- end
- return self
- end
- -------------------------------------------------------------------
- -- Basic targeter tab
- -- fills 18x51 tab with widgets for basic targeter
- -- Input:
- -- targeterId (1, 2, ...)
- -- refTabWidget - empty 18x51 tab
- -- refTextInput - InputLine widget reference
- -- refTargetArray - target array reference
- -- refTargetArrDrawRow - function drawing target array elements
- -- Output:
- -- t1ListT - target list ref (for updates)
- -- TargeterCoroutine
- local function CreateTargeterTab(targeterId, refTabWidget,
- refTextInput, refTargetArray, refTargetArrDrawRow)
- local targeter1 = CreateTargeter(targeterId, Widgets.Logger)
- local t1l1 = Widgets.Label:new()
- t1l1:init(refTabWidget, 1, 1, 13, 1, true)
- t1l1.text = "Lasers:"
- local t1ListLg = Widgets.ListView:new()
- t1ListLg:init(refTabWidget, 1, 2, 10, 16, true)
- t1ListLg.isSelectable = true
- t1ListLg.isMultiSelectable = true
- t1ListLg.dataArray = targeter1.groups
- t1ListLg.drawRow = targeter1.DisplayGroup
- t1ListLg.onSelect = targeter1.OnGroupSelect
- table.insert(PeripheralManager.widgetsToUpdate, t1ListLg)
- local t1l2 = Widgets.Label:new()
- t1l2:init(refTabWidget, 12, 1, 7, 1, true)
- t1l2.text = "Target:"
- local t1l3 = Widgets.Label:new()
- t1l3:init(refTabWidget, 12, 2, 20, 1, true)
- t1l3.bgColor = colors.white
- t1l3.text = string.format("%7s,%4s,%7s", targeter1.GetTarget())
- local t1b1 = Widgets.Button:new()
- t1b1:init(refTabWidget, 32, 2, 5, 1, true)
- t1b1.caption = "ENTER"
- t1b1.refTextInput = refTextInput
- t1b1.refTargeter = targeter1
- t1b1.refDrawable = refTabWidget
- t1b1.onClick = function(self)
- if not self.refTextInput or not self.refTargeter
- or not self.refDrawable then
- Widgets.Logger.log("ERROR", "ref not set", "TargetSetBn")
- return
- end
- local str = self.refTextInput:processText("x, y, z: ", "")
- local tab = textutils.unserialize("{"..str.."}")
- if tab == nil then return end
- local x, y, z = table.unpack(tab)
- if x and type(x) == "number" and y and type(y) == "number"
- and z and type(z) == "number" then
- self.refTargeter.SetTarget(x, y, z)
- t1l3.text = string.format("%7s,%4s,%7s", self.refTargeter.GetTarget())
- self.refDrawable:draw()
- else
- Widgets.Logger.log("DEBUG", string.format("x,y,z=%s,%s,%s",
- x, y, z), "TargetSetBn")
- end
- end
- local t1b2 = Widgets.ButtonT:new()
- t1b2:init(refTabWidget, 40, 4, 7, 1, true)
- t1b2.caption = " BOOST"
- t1b2.fn = targeter1.ModeBoost
- local t1l6 = Widgets.Label:new()
- t1l6:init(refTabWidget, 40, 5, 7, 1, true)
- t1l6.text = "Repeats:"
- local t1b6 = Widgets.Button:new()
- t1b6:init(refTabWidget, 40, 6, 7, 1, true)
- t1b6.caption = tostring(targeter1.repeats)
- t1b6.refTargeter = targeter1
- t1b6.refTextInput = refTextInput
- t1b6.refDrawable = refTabWidget
- t1b6.onClick = function(self)
- if not self.refTextInput or not self.refTargeter
- or not self.refDrawable then
- Widgets.Logger.log("ERROR", "ref not set", "RepeatsBn")
- return
- end
- local val = tonumber(self.refTextInput:processText(
- "Number of repeats: ", tostring(self.refTargeter.repeats)))
- if not val then return end
- val = math.floor(math.abs(val))
- if val <= 0 then return end
- self.refTargeter.repeats = val
- self.caption = tostring(val)
- self.refDrawable:draw()
- end
- local t1l7 = Widgets.Label:new()
- t1l7:init(refTabWidget, 40, 7, 7, 1, true)
- t1l7.text = "Delay:"
- local t1b7 = Widgets.Button:new()
- t1b7:init(refTabWidget, 40, 8, 7, 1, true)
- t1b7.caption = tostring(targeter1.repeatDelay.." s")
- t1b7.refTargeter = targeter1
- t1b7.refTextInput = refTextInput
- t1b7.refDrawable = refTabWidget
- t1b7.onClick = function(self)
- if not self.refTextInput or not self.refTargeter
- or not self.refDrawable then
- Widgets.Logger.log("ERROR", "ref not set", "RepeatDelayBn")
- return
- end
- local val = tonumber(self.refTextInput:processText(
- "Seconds between repeats: ",
- tostring(self.refTargeter.repeatDelay)))
- if not val then return end
- val = math.floor(math.abs(val)*20)/20
- if val < 0.05 then return end
- self.refTargeter.repeatDelay = val
- self.caption = tostring(val).." s"
- self.refDrawable:draw()
- end
- local t1b3 = Widgets.ButtonM:new()
- t1b3:init(refTabWidget, 45, 14, 6, 2, true)
- t1b3.text = " \n FIRE \n"
- t1b3.refTargeter = targeter1
- t1b3.onClick = function(self)
- if not self.refTargeter then
- Widgets.Logger.log("ERROR", "ref not set", "FireBn")
- return
- end
- self.refTargeter.isAborted = false
- if not self.refTargeter.isFiring then
- os.queueEvent("fire", targeterId)
- end
- end
- local t1l4 = Widgets.Label:new()
- t1l4:init(refTabWidget, 38, 1, 7, 1, true)
- t1l4.text = "Status:"
- local t1LStatus = Widgets.Label:new()
- t1LStatus:init(refTabWidget, 38, 2, 10, 1, true)
- t1LStatus.bgColor = colors.blue
- targeter1.SetStatusWidget(t1LStatus)
- local t1l5 = Widgets.Label:new()
- t1l5:init(refTabWidget, 12, 3, 13, 1, true)
- t1l5.text = "Target list:"
- -- target list viewer/selector
- local t1ListT = Widgets.ListView:new()
- t1ListT:init(refTabWidget, 12, 4, 25, 14, true)
- t1ListT.isSelectable = true
- t1ListT.dataArray = refTargetArray
- t1ListT.drawRow = refTargetArrDrawRow
- table.insert(ttB1.refDrawableArr, t1ListT)
- local t1b4 = Widgets.Button:new()
- t1b4:init(refTabWidget, 27, 3, 3, 1, true)
- t1b4.caption = " \30 "
- t1b4.refListT = t1ListT
- t1b4.refTargeter = targeter1
- t1b4.refTargetLabel = t1l3
- t1b4.refDrawable = refTabWidget
- t1b4.onClick = function(self)
- if not self.refListT or not self.refTargeter
- or not self.refDrawable or not self.refTargetLabel then
- Widgets.Logger.log("ERROR", "ref not set", "t1b4")
- return
- end
- Widgets.Logger.log("ERROR",
- "selected="..tostring(self.refListT.selected), "t1b4")
- if self.refListT.selected then
- local ts = self.refListT.dataArray[self.refListT.selected]
- self.refTargeter.SetTarget(ts[1], ts[2], ts[3])
- self.refTargetLabel.text = string.format("%7s,%4s,%7s",
- targeter1.GetTarget())
- self.refDrawable:draw()
- end
- end
- t1b5 = Widgets.ButtonM:new()
- t1b5:init(refTabWidget, 45, 17, 6, 1, true)
- t1b5.text = "ABORT "
- t1b5.textColor = colors.red
- t1b5.refTargeter = targeter1
- t1b5.onClick = function(self)
- if not self.refTargeter then
- Widgets.Logger.log("ERROR", "ref not set", "FireBn")
- return
- end
- self.refTargeter.isAborted = true
- end
- return t1ListT, targeter1.TargeterCoroutine
- end
- -------------------------------------------------------------------
- -- Automatic targeter tab for laser cameras
- -- fills 18x51 tab with widgets for automatic targeter
- -- Input:
- -- targeterId (1, 2, ...) - should be unique
- -- refTabWidget - empty 18x51 tab
- -- refTextInput - InputLine widget reference
- -- refTargetArray - target array reference
- -- refTargetArrDrawRow - function drawing target array elements
- -- Output:
- -- t1ListT - target list ref (for updates)
- -- TargeterCoroutine
- local function CreateTargeterAutoCamTab(targeterId, refTabWidget,
- refTextInput, refTargetArray, refTargetArrDrawRow)
- local targeter1 = CreateTargeterAutoCam(targeterId, Widgets.Logger)
- local t1l1 = Widgets.Label:new()
- t1l1:init(refTabWidget, 1, 1, 13, 1, true)
- t1l1.text = "Lasers:"
- local t1ListLg = Widgets.ListView:new()
- t1ListLg:init(refTabWidget, 1, 2, 10, 16, true)
- t1ListLg.isSelectable = true
- t1ListLg.isMultiSelectable = true
- t1ListLg.dataArray = targeter1.groups
- t1ListLg.drawRow = targeter1.DisplayGroup
- t1ListLg.onSelect = targeter1.OnGroupSelect
- table.insert(PeripheralManager.widgetsToUpdate, t1ListLg)
- local t1l2 = Widgets.Label:new()
- t1l2:init(refTabWidget, 12, 1, 7, 1, true)
- t1l2.text = "Target:"
- local t1l3 = Widgets.Label:new()
- t1l3:init(refTabWidget, 12, 2, 20, 1, true)
- t1l3.bgColor = colors.white
- t1l3.text = string.format("%7s,%4s,%7s", targeter1.GetTarget())
- local t1b1 = Widgets.Button:new()
- t1b1:init(refTabWidget, 32, 2, 5, 1, true)
- t1b1.caption = "ENTER"
- t1b1.refTextInput = refTextInput
- t1b1.refTargeter = targeter1
- t1b1.refDrawable = refTabWidget
- t1b1.onClick = function(self)
- if not self.refTextInput or not self.refTargeter
- or not self.refDrawable then
- Widgets.Logger.log("ERROR", "ref not set", "TargetSetBn")
- return
- end
- local str = self.refTextInput:processText("x, y, z: ", "")
- local tab = textutils.unserialize("{"..str.."}")
- if tab == nil then return end
- local x, y, z = table.unpack(tab)
- if x and type(x) == "number" and y and type(y) == "number"
- and z and type(z) == "number" then
- self.refTargeter.SetTarget(x, y, z)
- t1l3.text = string.format("%7s,%4s,%7s", self.refTargeter.GetTarget())
- self.refDrawable:draw()
- else
- Widgets.Logger.log("DEBUG", string.format("x,y,z=%s,%s,%s",
- x, y, z), "TargetSetBn")
- end
- end
- local t1b2 = Widgets.ButtonT:new()
- t1b2:init(refTabWidget, 40, 4, 7, 1, true)
- t1b2.caption = " BOOST"
- t1b2.fn = targeter1.ModeBoost
- local t1l6 = Widgets.Label:new()
- t1l6:init(refTabWidget, 40, 5, 7, 1, true)
- t1l6.text = "Repeats:"
- local t1b6 = Widgets.Button:new()
- t1b6:init(refTabWidget, 40, 6, 7, 1, true)
- t1b6.caption = tostring(targeter1.repeats)
- t1b6.refTargeter = targeter1
- t1b6.refTextInput = refTextInput
- t1b6.refDrawable = refTabWidget
- t1b6.onClick = function(self)
- if not self.refTextInput or not self.refTargeter
- or not self.refDrawable then
- Widgets.Logger.log("ERROR", "ref not set", "RepeatsBn")
- return
- end
- local val = tonumber(self.refTextInput:processText(
- "Number of repeats: ", tostring(self.refTargeter.repeats)))
- if not val then return end
- val = math.floor(math.abs(val))
- if val <= 0 then return end
- self.refTargeter.repeats = val
- self.caption = tostring(val)
- self.refDrawable:draw()
- end
- local t1l7 = Widgets.Label:new()
- t1l7:init(refTabWidget, 40, 7, 7, 1, true)
- t1l7.text = "Delay:"
- local t1b7 = Widgets.Button:new()
- t1b7:init(refTabWidget, 40, 8, 7, 1, true)
- t1b7.caption = tostring(targeter1.repeatDelay.." s")
- t1b7.refTargeter = targeter1
- t1b7.refTextInput = refTextInput
- t1b7.refDrawable = refTabWidget
- t1b7.onClick = function(self)
- if not self.refTextInput or not self.refTargeter
- or not self.refDrawable then
- Widgets.Logger.log("ERROR", "ref not set", "RepeatDelayBn")
- return
- end
- local val = tonumber(self.refTextInput:processText(
- "Seconds between repeats: ",
- tostring(self.refTargeter.repeatDelay)))
- if not val then return end
- val = math.floor(math.abs(val)*20)/20
- if val < 0.05 then return end
- self.refTargeter.repeatDelay = val
- self.caption = tostring(val).." s"
- self.refDrawable:draw()
- end
- local t1b3 = Widgets.ButtonM:new()
- t1b3:init(refTabWidget, 45, 14, 6, 2, true)
- t1b3.text = " \n FIRE \n"
- t1b3.refTargeter = targeter1
- t1b3.onClick = function(self)
- if not self.refTargeter then
- Widgets.Logger.log("ERROR", "ref not set", "FireBn")
- return
- end
- self.refTargeter.isAborted = false
- if not self.refTargeter.isFiring then
- os.queueEvent("fire", targeterId)
- end
- end
- local t1l4 = Widgets.Label:new()
- t1l4:init(refTabWidget, 38, 1, 7, 1, true)
- t1l4.text = "Status:"
- local t1LStatus = Widgets.Label:new()
- t1LStatus:init(refTabWidget, 38, 2, 10, 1, true)
- t1LStatus.bgColor = colors.blue
- targeter1.SetStatusWidget(t1LStatus)
- local t1l5 = Widgets.Label:new()
- t1l5:init(refTabWidget, 12, 3, 13, 1, true)
- t1l5.text = "Target list:"
- -- target list viewer/selector
- local t1ListT = Widgets.ListView:new()
- t1ListT:init(refTabWidget, 12, 4, 25, 14, true)
- t1ListT.isSelectable = true
- t1ListT.dataArray = refTargetArray
- t1ListT.drawRow = refTargetArrDrawRow
- table.insert(ttB1.refDrawableArr, t1ListT)
- local t1b4 = Widgets.Button:new()
- t1b4:init(refTabWidget, 27, 3, 3, 1, true)
- t1b4.caption = " \30 "
- t1b4.refListT = t1ListT
- t1b4.refTargeter = targeter1
- t1b4.refTargetLabel = t1l3
- t1b4.refDrawable = refTabWidget
- t1b4.onClick = function(self)
- if not self.refListT or not self.refTargeter
- or not self.refDrawable or not self.refTargetLabel then
- Widgets.Logger.log("ERROR", "ref not set", "t1b4")
- return
- end
- Widgets.Logger.log("ERROR",
- "selected="..tostring(self.refListT.selected), "t1b4")
- if self.refListT.selected then
- local ts = self.refListT.dataArray[self.refListT.selected]
- self.refTargeter.SetTarget(ts[1], ts[2], ts[3])
- self.refTargetLabel.text = string.format("%7s,%4s,%7s",
- targeter1.GetTarget())
- self.refDrawable:draw()
- end
- end
- t1b5 = Widgets.ButtonM:new()
- t1b5:init(refTabWidget, 45, 17, 6, 1, true)
- t1b5.text = "ABORT "
- t1b5.textColor = colors.red
- t1b5.refTargeter = targeter1
- t1b5.onClick = function(self)
- if not self.refTargeter then
- Widgets.Logger.log("ERROR", "ref not set", "FireBn")
- return
- end
- self.refTargeter.isAborted = true
- end
- return t1ListT, targeter1.TargeterCoroutine
- end
- -------------------------------------------------------------------
- -- Peripheral manager tab
- -- fills 18x51 tab with a GUI to manage all connected peripherals
- -- uses existing PeripheralManager from this file
- -- Input:
- -- refTabWidget - empty 18x51 tab
- -- refTextInput - InputLine widget reference
- local function CreatePeripheralManagerTab(refTabWidget,
- refTextInput)
- local tpml1 = Widgets.Label:new()
- tpml1:init(refTabWidget, 1, 1, 12, 1, true)
- tpml1.text = "Peripherals:"
- -- List of every connected peripheral side/name
- local tpmList1 = Widgets.ListView:new()
- tpmList1:init(refTabWidget, 1, 2, 20, 15, true)
- tpmList1.isSelectable = true
- tpmList1.includeCfg = function() return true end
- tpmList1.refPerManTable = PeripheralManager.peripherals
- tpmList1.onSelect = function(self)
- if not self.refMethods or not self.refPerData then
- Widgets.Logger.log("ERROR", "ref not set", "tpmList1")
- return
- end
- self.refMethods.dataArray = nil
- if self.selected and self.dataArray then
- local perSide = self.dataArray[self.selected]
- if peripheral.isPresent(perSide) then
- self.refMethods.dataArray = peripheral.getMethods(perSide)
- end
- end
- self:drawRefs()
- end
- tpmList1.updateData = function(self)
- self.dataArray = peripheral.getNames()
- if self.includeCfg() and self.refPerManTable then
- for k, _ in pairs(self.refPerManTable) do
- if not peripheral.isPresent(k) then
- table.insert(self.dataArray, k)
- end
- end
- end
- table.sort(self.dataArray)
- end
- local tpmList1fn = function(newVal)
- local value = true --default
- return function(newVal)
- if newVal==nil then return value end
- if newVal==true then value = true end
- if newVal==false then value = false end
- end
- end
- tpmList1.includeCfg = tpmList1fn()
- tpmList1.drawRow = function(self, index, length, isSelected)
- local bgColor = self.bgColor
- local textColor = self.textColor
- local val = self.dataArray[index] --peripheral name
- local shortName = val:gsub("warpdrive", "wd", 1) --shorten prefix
- if shortName:len() > 20 then --we're limited to 20 chars
- local numStart, numEnd = shortName:find("_%d+", 3)
- if numStart and numEnd then
- shortName = shortName:sub(1, 20-(numEnd-numStart+1)) .. "~"
- .. shortName:sub(numStart+1, numEnd)
- end
- end
- if self.refPerManTable and val
- and (not self.refPerManTable[val]
- or not self.refPerManTable[val].callable) then
- textColor = colors.gray
- end
- if isSelected then
- bgColor = self.bgColorSelected
- end
- local rowStr = string.format("%-"..length.."."..length.."s",
- shortName)
- self.window.blit(rowStr,
- colorToBlit(textColor):rep(#rowStr),
- colorToBlit(bgColor):rep(#rowStr))--]]
- end
- -- Button to refresh the list of peripherals
- local tpmb1 = Widgets.Button:new()
- tpmb1:init(refTabWidget, 1, 17, 7, 1, true)
- tpmb1.caption = "REFRESH"
- tpmb1.refListPeripherals = tpmList1
- tpmb1.onClick = function(self)
- if not self.refListPeripherals then
- Widgets.Logger.log("ERROR", "refListPeripherals not set", "tpmb1")
- return
- end
- self.refListPeripherals:draw()
- end
- -- Button to include/exclude disconnected peripherals from .cfg
- local tpmBT1 = Widgets.ButtonT:new()
- tpmBT1:init(refTabWidget, 9, 17, 5, 1, true)
- tpmBT1.caption = ".cfg"
- tpmBT1.refListPeripherals = tpmList1
- tpmBT1.fn = tpmList1.includeCfg
- -- Methods and data tabs
- local tpmTabs1 = Widgets.Tabs:new()
- tpmTabs1:init(refTabWidget, 22, 1, 31, 49, true)
- -- Methods tab
- local tpmTab1 = tpmTabs1:addTab(" Methods ")
- -- List of all methods of selected peripheral
- local tpmList2 = Widgets.ListView:new()
- tpmList2:init(tpmTab1, 1, 2, 20, 8, true)
- tpmList2.isSelectable = true
- tpmList1.refMethods = tpmList2
- table.insert(tpmList1.refsDraw, tpmList2)
- -- Function to perform all the checks and make the call
- local tpmBtnCallFunc = function(self, askParams)
- if not self.refMethods or not self.refListPeripherals
- or not self.refLabelResult then
- Widgets.Logger.log("ERROR", "reference not set", "tpmBtnCallFunc")
- return
- end
- self.refLabelResult.text = ""
- local selectedIndexMethod = self.refMethods.selected
- local selectedIndexName = self.refListPeripherals.selected
- if selectedIndexMethod and selectedIndexName
- and self.refMethods.dataArray
- and self.refListPeripherals.dataArray then
- local selectedMethod = self.refMethods.dataArray[selectedIndexMethod]
- local selectedName = self.refListPeripherals.dataArray[selectedIndexName]
- if selectedMethod and selectedName then
- --user params
- local parTable = {}
- if askParams then
- if not self.refTextInput then
- Widgets.Logger.log("ERROR", "refTextInput not set", "tpmBtnCallFunc")
- else
- local parStr = self.refTextInput:processText("Params: ", "")
- parTable = textutils.unserialize("{"..parStr.."}")
- if parTable == nil then return end
- end
- end
- --call method + params
- local res = table.pack(pcall(function()
- return peripheral.call(selectedName, selectedMethod,
- table.unpack(parTable)) end))
- --show what has been called
- self.refLabelResult.text = selectedName.."."..selectedMethod.."("
- if (parTable) then
- for i_p = 1, #parTable do
- self.refLabelResult.text = self.refLabelResult.text..tostring(parTable[i_p])
- if i_p < #parTable then
- self.refLabelResult.text = self.refLabelResult.text..", "
- end
- end
- end
- self.refLabelResult.text = self.refLabelResult.text..")\n"
- --process call results
- res.n = nil
- if res[1] then
- self.refLabelResult.textColor = colors.white
- for i_r = 2, #res do
- self.refLabelResult.text = self.refLabelResult.text..tostring(res[i_r])
- if i_r < #res then
- self.refLabelResult.text = self.refLabelResult.text..", "
- end
- end
- else
- self.refLabelResult.textColor = colors.red
- self.refLabelResult.text = self.refLabelResult.text..tostring(res[2])
- end
- end
- end
- self.refLabelResult:draw()
- end
- -- Button to call the selected method
- local tpmB2 = Widgets.Button:new()
- tpmB2:init(tpmTab1, 23, 2, 6, 1, true)
- tpmB2.caption = " CALL "
- tpmB2.refMethods = tpmList2
- tpmB2.refListPeripherals = tpmList1
- tpmB2.onClick = function(self)
- tpmBtnCallFunc(self)
- end
- -- Button to call the selected method with user params
- local tpmB3 = Widgets.ButtonM:new()
- tpmB3:init(tpmTab1, 23, 4, 6, 3, true)
- tpmB3.text = " CALL \n WITH \nPARAMS"
- tpmB3.refMethods = tpmList2
- tpmB3.refListPeripherals = tpmList1
- tpmB3.refTextInput = refTextInput
- tpmB3.onClick = function(self)
- tpmBtnCallFunc(self, true)
- end
- -- Label to display the results of the call
- local tpmL2 = Widgets.Label:new()
- tpmL2:init(tpmTab1, 1, 11, 29, 5, true)
- tpmL2.bgColor = colors.gray
- tpmL2.text = "Method call results\nshould appear here"
- tpmB2.refLabelResult = tpmL2
- tpmB3.refLabelResult = tpmL2
- -- Data tab
- local tpmTab2 = tpmTabs1:addTab(" Data ")
- local tpmL3 = Widgets.Label:new()
- tpmL3:init(tpmTab2, 1, 1, 10, 1, true)
- tpmL3.text = "In memory:"
- local tpmListPerData = Widgets.ListView:new()
- tpmListPerData:init(tpmTab2, 1, 2, 29, 14, true)
- tpmListPerData.refPerManTable = PeripheralManager.peripherals
- tpmListPerData.refListPeripherals = tpmList1
- tpmList1.refPerData = tpmListPerData
- table.insert(tpmList1.refsDraw, tpmListPerData)
- tpmListPerData.updateData = function(self)
- self.dataArray = {}
- if not self.refPerManTable or not self.refListPeripherals then
- Widgets.Logger.log("ERROR", "ref not set", "tpmListPerData")
- return
- end
- local sel = self.refListPeripherals.selected
- local da = self.refListPeripherals.dataArray
- if not sel or not da then return end
- local selName = da[sel]
- if not selName or not self.refPerManTable[selName] then return end
- local res = ConvertTableToArrayStrings(
- self.refPerManTable[selName])
- if res then self.dataArray = res end
- end
- table.insert(PeripheralManager.widgetsToUpdate, tpmListPerData)
- -- .cfg tab
- local tpmTab3 = tpmTabs1:addTab(".cfg ")
- local tpmL4 = Widgets.Label:new()
- tpmL4:init(tpmTab3, 1, 1, 10, 1, true)
- tpmL4.text = "On disk:"
- local tpmListPerCfg = Widgets.ListView:new()
- tpmListPerCfg:init(tpmTab3, 1, 2, 30, 14, true)
- tpmListPerCfg.refListPeripherals = tpmList1
- tpmListPerCfg.isSelectable = true
- table.insert(tpmList1.refsDraw, tpmListPerCfg)
- tpmListPerCfg.getSelPeripheral = function(self)
- if not self.refListPeripherals then
- Widgets.Logger.log("ERROR", "ref not set", "tpmListPerCfg")
- return
- end
- local sel = self.refListPeripherals.selected
- local da = self.refListPeripherals.dataArray
- if not sel or not da then return end
- self.selectedPeripheral = da[sel]
- end
- tpmListPerCfg.updateData = function(self)
- self.dataArray = {}
- self:getSelPeripheral()
- if not self.selectedPeripheral or not self.cfgTable then
- return
- end
- if self.cfgTable[self.selectedPeripheral] then
- local arr, ind = ConvertTableToArraySerialize(
- self.cfgTable[self.selectedPeripheral])
- if arr then self.dataArray = arr else return end
- if ind then self.dataInd = ind else return end
- end
- end
- --Button to reload .cfg file to memory for edit
- local tpmB4 = Widgets.Button:new()
- tpmB4:init(tpmTab3, 19, 16, 6, 1, true)
- tpmB4.caption = "RELOAD"
- tpmB4.refList = tpmListPerCfg
- tpmB4.refTextInput = refTextInput
- tpmB4.onClick = function(self)
- if not self.refList or not self.refTextInput then
- Widgets.Logger.log("ERROR", "ref not set", "RELOAD")
- return
- end
- self.refList.cfgTable = {}
- if not PeripheralManager.ReadPeripheralTable(
- self.refList.cfgTable) then
- self.refList.cfgTable = nil
- refTextInput:showMessage("["..os.date("%T")
- .."] Failed to load config")
- return
- end
- refTextInput:showMessage("["..os.date("%T")
- .."] Config loaded")
- self.refList:draw()
- end
- -- Button to write new .cfg from memory (if there's a table in there)
- local tpmB5 = Widgets.Button:new()
- tpmB5:init(tpmTab3, 26, 16, 5, 1, true)
- tpmB5.caption = "WRITE"
- tpmB5.refList = tpmListPerCfg
- tpmB5.refTextInput = refTextInput
- tpmB5.onClick = function(self)
- if not self.refList or not tpmB5.refTextInput then
- Widgets.Logger.log("ERROR", "ref not set", "WRITE")
- return
- end
- if not self.refList.cfgTable
- or type(self.refList.cfgTable)~="table" then
- Widgets.Logger.log("ERROR", "broken cfgTable", "WRITE")
- refTextInput:showMessage("["..os.date("%T")
- .."] In-mem config is broken")
- return
- end
- if not PeripheralManager.WritePeripheralTable(
- self.refList.cfgTable) then
- refTextInput:showMessage("["..os.date("%T")
- .."] Failed to write config")
- return
- end
- refTextInput:showMessage("["..os.date("%T").."] Config written")
- end
- -- Button to add new key=true for the selected peripheral
- local tpmB6 = Widgets.Button:new()
- tpmB6:init(tpmTab3, 1, 16, 3, 1, true)
- tpmB6.caption = "ADD"
- tpmB6.refList = tpmListPerCfg
- tpmB6.refTextInput = refTextInput
- tpmB6.onClick = function(self)
- if not self.refList or not self.refTextInput then
- Widgets.Logger.log("ERROR", "ref not set", "ADD")
- return
- end
- if not self.refList.cfgTable then return end
- local selName = self.refList.selectedPeripheral
- if not selName then return end
- local key = textutils.unserialize(self.refTextInput:processText(
- "New key: ", ""))
- if key == nil then
- Widgets.Logger.log("DEBUG", "key == nil", "ADD")
- return end
- if not self.refList.cfgTable[selName] then
- self.refList.cfgTable[selName] = {}
- end
- local cfgSelected = self.refList.cfgTable[selName]
- cfgSelected[key] = true
- self.refList:draw()
- end
- -- Button to remove selected kv pair for the selected peripheral
- local tpmB7 = Widgets.Button:new()
- tpmB7:init(tpmTab3, 10, 16, 3, 1, true)
- tpmB7.caption = "REM"
- tpmB7.refList = tpmListPerCfg
- tpmB7.onClick = function(self)
- if not self.refList then
- Widgets.Logger.log("ERROR", "ref not set", "REM")
- return
- end
- if not self.refList.cfgTable then return end
- local cfgTable = self.refList.cfgTable
- if not self.refList.selectedPeripheral then return end
- local selectedPeripheral = self.refList.selectedPeripheral
- if not self.refList.selected then return end
- local selIndex = self.refList.selected
- if not self.refList.dataInd then return end
- local di = self.refList.dataInd
- if not di[selIndex] then return end
- if not cfgTable[selectedPeripheral] then return end
- cfgTable[selectedPeripheral][di [selIndex] ] = nil
- self.refList:draw()
- end
- -- Button to edit value for the selected kv pair
- local tpmB8 = Widgets.Button:new()
- tpmB8:init(tpmTab3, 5, 16, 4, 1, true)
- tpmB8.caption = "EDIT"
- tpmB8.refList = tpmListPerCfg
- tpmB8.refTextInput = refTextInput
- tpmB8.onClick = function(self)
- if not self.refList or not self.refTextInput then
- Widgets.Logger.log("ERROR", "ref not set", "EDIT")
- return
- end
- if not self.refList.cfgTable then return end
- local cfgTable = self.refList.cfgTable
- if not self.refList.selectedPeripheral then return end
- local selectedPeripheral = self.refList.selectedPeripheral
- if not self.refList.selected then return end
- local selIndex = self.refList.selected
- if not self.refList.dataInd then return end
- local di = self.refList.dataInd
- if not di[selIndex] then return end
- if not cfgTable[selectedPeripheral] then return end
- local curVal = cfgTable[selectedPeripheral][di [selIndex] ]
- curVal = string.gsub(textutils.serialize(curVal), "\n", "")
- local str = self.refTextInput:processText(tostring(di[selIndex])
- ..": ", curVal)
- local val = textutils.unserialize(str)
- if val == nil then return end
- cfgTable[selectedPeripheral][di [selIndex] ] = val
- self.refList:draw()
- end
- -- Button to set default values for the selected peripheral
- local tpmB9 = Widgets.Button:new()
- tpmB9:init(tpmTab3, 14, 16, 1, 1, true)
- tpmB9.caption = "D"
- tpmB9.refList = tpmListPerCfg
- tpmB9.onClick = function(self)
- if not self.refList then
- Widgets.Logger.log("ERROR", "ref not set", "D")
- return
- end
- if not self.refList.cfgTable then return end
- local selName = self.refList.selectedPeripheral
- if not selName then return end
- local t = peripheral.getType(selName)
- if not t then return end
- self.refList.cfgTable[selName] =
- PeripheralManager.GetDefaultParamsByType(t)
- self.refList:draw()
- end
- tpmTabs1:selectTab(" Data ")
- end
- local ExportedUtils =
- {
- ReadTableFromFile = ReadTableFromFile,
- WriteTableToFile = WriteTableToFile,
- PeripheralManager = PeripheralManager,
- CreateTargeter = CreateTargeter,
- CreateTargeterTab = CreateTargeterTab,
- CreateTargeterAutoCamTab = CreateTargeterAutoCamTab,
- CreatePeripheralManagerTab = CreatePeripheralManagerTab,
- ColorToBlit = colorToBlit,
- ConvertTableToArrayStrings = ConvertTableToArrayStrings,
- ConvertTableToArraySerialize = ConvertTableToArraySerialize
- }
- return ExportedUtils
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement