annotate Devian.lua @ 14:5254d1ba6013 v1.2-r15

Multiple output windows can be created for different output prefixes, and prefixes can be designated to an existing or new "console" with /dvn <prefix> <console> Frame objects are generated directly from XML data, and their state information is stored in the object itself to resolve issues with GetWidth() returning old info in some cases. StackFrames and DistributeFrames methods can be invoked from /script to arrange the buffers.
author Nenue
date Sun, 20 Dec 2015 00:46:42 -0500
parents 080dfa4990fb
children 48a1d9c14af5
rev   line source
Nenue@0 1 -- User: Krakyn
Nenue@0 2 -- Created: 11/30/2015 7:46 AM
Nenue@0 3 if not LibStub then
Nenue@0 4 print('Something has happened...')
Nenue@0 5 end
Nenue@0 6 Devian = LibStub("AceAddon-3.0"):NewAddon("Devian", "AceConsole-3.0", "AceEvent-3.0")
Nenue@13 7 local MAJOR, MINOR = 'Devian-1.3', 'r@project-revision@'
Nenue@0 8 local D = _G.Devian
Nenue@0 9 local STATE_LOW, STATE_HIGH = 1, 2
Nenue@0 10 local PLAYER_REALM = UnitName("player") .. '-' .. GetRealmName()
Nenue@13 11 local DEVIAN_FRAME = 'DevianConsole'
Nenue@7 12 local print = function(...)
Nenue@13 13 _G.print('Dvn', ...)
Nenue@7 14 end
Nenue@9 15 local db
Nenue@13 16 local defaults = {
Nenue@13 17 ['global'] = {[STATE_LOW] = {}, [STATE_HIGH] = {}},
Nenue@13 18 ['tags'] = {},
Nenue@13 19 ['channels'] = {[1] = {signature = 'Dvn', name = 'Main', header = "%n [%t]", x = 100, y = 800, height = 500, width = 600, enabled = true}},
Nenue@14 20 primary_channel = 1,
Nenue@13 21 current_channel = 1,
Nenue@14 22 toggle = true,
Nenue@13 23 dnd_status = true,
Nenue@13 24 dnd_message = "Debugging. Your messages may get eaten.",
Nenue@13 25 font = [[Interface\Addons\Devian\font\SourceCodePro-Regular.ttf]],
Nenue@13 26 fontsize = 13,
Nenue@13 27 fontoutline = 'NONE',
Nenue@14 28 backdrop = {1,1,1,0.2},
Nenue@14 29 backgrad = {'VERTICAL', 0.1, 0.1, 0.1, 0.3, 0, 0, 0, 0.5},
Nenue@14 30 backblend = 'BLEND',
Nenue@14 31 frontdrop = {1,1,1,1},
Nenue@14 32 frontgrad = {'VERTICAL', 0.1, 0.1, 0.1, 0.9, 0, 0, 0, 0.9},
Nenue@14 33 frontblend = 'BLEND'
Nenue@13 34 }
Nenue@9 35
Nenue@4 36
Nenue@13 37 local function ScanAddOnList(cmd, ...)
Nenue@0 38 local list_state
Nenue@0 39
Nenue@14 40 local args = {}
Nenue@14 41 local arg, n = D:GetArgs(cmd, 1)
Nenue@14 42 while arg do
Nenue@14 43 table.insert(args, arg)
Nenue@14 44 arg, n = D:GetArgs(cmd,1,n)
Nenue@14 45 end
Nenue@14 46 local mode, tag, dest = unpack(args)
Nenue@0 47
Nenue@13 48
Nenue@14 49 -- no args, toggle ui
Nenue@0 50 if mode == nil then
Nenue@0 51 list_state = db.enabled and STATE_LOW or STATE_HIGH
Nenue@0 52 db.enabled = (db.enabled == false) and true or false
Nenue@0 53 print(list_state, db.enabled)
Nenue@0 54
Nenue@0 55 if list_state == STATE_LOW then
Nenue@0 56 end
Nenue@14 57 elseif mode == 'stack' then
Nenue@14 58 return D:StackFrames()
Nenue@14 59 elseif mode == 'grid' then
Nenue@14 60 return D:DistributeFrames()
Nenue@14 61 elseif mode == 'tag' then -- tagging
Nenue@14 62 if tag ~= nil and dest ~= nil then
Nenue@14 63 if not D.console[dest] and not D.sig[dest] then
Nenue@14 64 local sig = dest:match('%a')
Nenue@14 65 local id = dest:match('%d')
Nenue@14 66 if not id then
Nenue@14 67 id = self.last_channel + 1
Nenue@14 68 end
Nenue@14 69 if not sig then
Nenue@14 70 sig = tag
Nenue@14 71 end
Nenue@14 72 D:SetChannel(sig, id)
Nenue@14 73 end
Nenue@14 74 D:Print('Assigning |cFFFFFF00'..tag..'|r to |cFF00FFFF'.. dest .. '|r')
Nenue@14 75 else
Nenue@14 76 D:Print('Usage: /dvn tag <prefix> <console name or number>')
Nenue@14 77 end
Nenue@14 78 return
Nenue@14 79 elseif mode ~= nil then
Nenue@14 80 mode = tonumber(mode)
Nenue@0 81 if mode > 2 then
Nenue@13 82 print('Something has happened.')
Nenue@0 83 return
Nenue@0 84 end
Nenue@0 85 list_state = mode == STATE_LOW and STATE_LOW or STATE_HIGH
Nenue@0 86 end
Nenue@0 87 local char_list, global_list = db[PLAYER_REALM][list_state], db.global[list_state]
Nenue@0 88
Nenue@0 89 local playername = UnitName("player")
Nenue@0 90
Nenue@0 91 for i = 1, GetNumAddOns() do
Nenue@0 92 local name = GetAddOnInfo(i)
Nenue@0 93 local enableState, globalState = GetAddOnEnableState(playername, i), GetAddOnEnableState(nil, i)
Nenue@0 94
Nenue@0 95 if mode == STATE_LOW or mode == STATE_HIGH then
Nenue@0 96 char_list[name] = enableState
Nenue@0 97 global_list[name] = globalState
Nenue@0 98 else
Nenue@13 99 if char_list[name] or global_list[name] then
Nenue@0 100
Nenue@0 101 if char_list[name] ~= 0 and global_list[name] ~= 0 then
Nenue@0 102 local value = false
Nenue@0 103 if char_list[name] == 2 and global_list[name] == 1 then
Nenue@0 104 value = UnitName("player")
Nenue@0 105 elseif global_list[name] == 2 then
Nenue@0 106 value = true
Nenue@0 107 end
Nenue@0 108 print('EnableAddOn(', i, ',', value,')')
Nenue@0 109 EnableAddOn(i, value)
Nenue@0 110 else
Nenue@0 111 local value = true
Nenue@0 112 if char_list[name] == 2 and global_list[name] == 1 then
Nenue@0 113 value = UnitName("player")
Nenue@0 114 end
Nenue@0 115 print('DisableAddOn(', i, ',', value,')')
Nenue@0 116 DisableAddOn(i,value)
Nenue@0 117 end
Nenue@13 118 end
Nenue@0 119
Nenue@0 120 end
Nenue@0 121 end
Nenue@0 122
Nenue@0 123 if mode == nil then
Nenue@0 124 ReloadUI()
Nenue@0 125 end
Nenue@0 126 if mode == STATE_LOW then
Nenue@0 127 D:Print('Developement AddOn list saved.')
Nenue@0 128 else
Nenue@0 129 D:Print('Standard AddOn list saved.')
Nenue@0 130 end
Nenue@0 131 end
Nenue@0 132
Nenue@0 133
Nenue@13 134 local function Console_MinMax(self)
Nenue@13 135 if self.minimized then
Nenue@7 136 self:Maximize()
Nenue@7 137 else
Nenue@7 138 self:Minimize()
Nenue@7 139 end
Nenue@7 140 end
Nenue@13 141
Nenue@13 142 local function Console_Minimize(self)
Nenue@13 143 self:SetHeight(20)
Nenue@13 144 self:SetMaxResize(GetScreenWidth(),20)
Nenue@13 145 self.minimized = true
Nenue@14 146 self.out:Hide()
Nenue@14 147 self:Save()
Nenue@7 148 end
Nenue@0 149
Nenue@13 150 local function Console_Maximize(self)
Nenue@13 151 local db = db.channels[self.index]
Nenue@13 152 self:SetHeight(db.height)
Nenue@13 153 self:SetMaxResize(GetScreenWidth(),GetScreenHeight())
Nenue@13 154 self.minimized = nil
Nenue@14 155 self.out:Show()
Nenue@14 156 self:Save()
Nenue@13 157 end
Nenue@13 158
Nenue@13 159
Nenue@13 160 local function Console_Save(self)
Nenue@13 161 local db = db.channels[self.index]
Nenue@14 162 if self.x then
Nenue@14 163 db.x = self.x
Nenue@14 164 else
Nenue@14 165 db.x = self:GetLeft()
Nenue@14 166 end
Nenue@14 167
Nenue@14 168 if self.y then
Nenue@14 169 db.y = self.y
Nenue@14 170 else
Nenue@14 171 db.y = (self:GetTop() - GetScreenHeight())
Nenue@14 172 end
Nenue@14 173
Nenue@14 174 if self.width then
Nenue@14 175 db.width = self.width
Nenue@14 176 else
Nenue@14 177 db.width = self:GetWidth()
Nenue@14 178 end
Nenue@14 179
Nenue@13 180 if not self.minimized then
Nenue@14 181 if self.height then
Nenue@14 182 db.height = self.height
Nenue@14 183 else
Nenue@14 184 db.height = self:GetHeight()
Nenue@14 185 end
Nenue@14 186 self:SetHeight(db.height)
Nenue@13 187 end
Nenue@14 188
Nenue@14 189 db.minimized = self.minimized and true or nil
Nenue@14 190 db.enabled = self:IsVisible() and true or nil
Nenue@14 191 db.active = self.active and true or nil
Nenue@14 192 print('save:', db.signature, 'min=', db.minimized, ' enabled=', db.enabled, ' active = ', db.active, 'x=', db.x, 'y=', db.y, 'h=', db.height, 'w=', db.width)
Nenue@13 193 self:SetPoint('TOPLEFT', UIParent, 'TOPLEFT', db.x, db.y)
Nenue@14 194 self:SetWidth(db.width)
Nenue@13 195 end
Nenue@13 196
Nenue@14 197 -- Console frame toggler
Nenue@14 198 -- @paramsig [...]
Nenue@14 199 -- @param ... one or more space-seperated channel keys
Nenue@13 200 local function Console_Toggle(input)
Nenue@14 201 local search = {}
Nenue@14 202 local key, n = D:GetArgs(input, 1)
Nenue@14 203 if key then
Nenue@14 204 repeat
Nenue@14 205 if D.sig[key] then
Nenue@14 206 table.insert(search, D.sig[key])
Nenue@14 207 elseif D.console[key] then
Nenue@14 208 table.insert(search, D.console[key])
Nenue@14 209 end
Nenue@14 210 key, n = D:GetArgs(input,1,n)
Nenue@14 211 until n == 1e9
Nenue@13 212 else
Nenue@13 213 search = D.console
Nenue@13 214 end
Nenue@13 215
Nenue@14 216 db.toggle = not db.toggle and true or nil
Nenue@13 217 for _, c in ipairs(search) do
Nenue@14 218 if db.toggle then
Nenue@14 219 c:Show()
Nenue@14 220 else
Nenue@14 221 c.enabled = nil
Nenue@14 222 c.minimized = nil
Nenue@14 223 c:Maximize()
Nenue@13 224 c:Hide()
Nenue@13 225 end
Nenue@13 226 end
Nenue@14 227
Nenue@14 228 if db.toggle then
Nenue@14 229 D:Print('toggled on?')
Nenue@14 230 else
Nenue@14 231 D:Print('toggled off?')
Nenue@14 232 end
Nenue@13 233 end
Nenue@13 234
Nenue@14 235 -- Bring console to the front
Nenue@14 236 local function Console_ToFront(c)
Nenue@14 237 --print(D.raise_ct, 'Raising', c.signature)
Nenue@14 238 --print(unpack(db.frontdrop))
Nenue@14 239 --print(unpack(db.frontgrad))
Nenue@14 240 --print(db.frontblend)
Nenue@14 241 D.raise_ct = D.raise_ct + 1
Nenue@14 242 c:Raise()
Nenue@14 243 c.out.backdrop:SetTexture(unpack(db.frontdrop))
Nenue@14 244 c.out.backdrop:SetGradientAlpha(unpack(db.frontgrad))
Nenue@14 245 c.out.backdrop:SetBlendMode(db.frontblend)
Nenue@14 246
Nenue@14 247 for id, bc in pairs(D.console) do
Nenue@14 248 if id ~= c.index then
Nenue@14 249 --print(D.raise_ct, 'Lowering', bc.signature)
Nenue@14 250 --print(unpack(db.backdrop))
Nenue@14 251 --print(unpack(db.backgrad))
Nenue@14 252 --print(db.backblend)
Nenue@14 253 bc.out.backdrop:SetTexture(unpack(db.backdrop))
Nenue@14 254 bc.out.backdrop:SetGradientAlpha(unpack(db.backgrad))
Nenue@14 255 bc.out.backdrop:SetBlendMode(db.backblend)
Nenue@14 256 end
Nenue@14 257 end
Nenue@14 258
Nenue@14 259 end
Nenue@14 260
Nenue@14 261 -- Generate a console frame
Nenue@14 262 -- @paramsig id, vars
Nenue@14 263 -- @param id channel number
Nenue@14 264 -- @param vars alternative config, else uses db.channels[id]
Nenue@13 265 local function CreateConsole(i, vars)
Nenue@14 266
Nenue@14 267 if not vars then
Nenue@14 268 vars = db.channels[i]
Nenue@14 269 end
Nenue@14 270
Nenue@14 271 print('make:', vars.signature, '(', vars.x, vars.y, ')', vars.width, 'x', vars.height)
Nenue@13 272 local f = CreateFrame('Frame', 'DevianChannelFrame' .. tostring(i), UIParent, DEVIAN_FRAME)
Nenue@14 273 f:SetPoint('TOPLEFT', UIParent, 'TOPLEFT', vars.x, vars.y)
Nenue@13 274 f:SetSize(vars.width, vars.height)
Nenue@13 275 f:Lower()
Nenue@13 276 f.out:SetFont(db.font, db.fontsize, db.fontoutline)
Nenue@13 277 f.Save = Console_Save
Nenue@13 278 f.Minimize = Console_Minimize
Nenue@13 279 f.Maximize = Console_Maximize
Nenue@13 280 f.MinMax = Console_MinMax
Nenue@14 281 f.ToFront = Console_ToFront
Nenue@13 282 f.Toggle = D.Console_Toggle
Nenue@13 283 f.name = vars.name
Nenue@13 284 f.index = i
Nenue@14 285 f.signature = vars.signature
Nenue@14 286 f.format = vars.header
Nenue@14 287 f.x = vars.x
Nenue@14 288 f.y = vars.y
Nenue@14 289 f.width = vars.width
Nenue@14 290 f.height = vars.height
Nenue@13 291
Nenue@14 292 if vars.enabled then
Nenue@14 293 f.enabled = true
Nenue@14 294 if db.toggle then
Nenue@14 295 f:Show()
Nenue@14 296 end
Nenue@13 297 end
Nenue@14 298 if vars.minimized then
Nenue@13 299 f:Minimize()
Nenue@13 300 end
Nenue@13 301
Nenue@13 302 return f
Nenue@13 303 end
Nenue@13 304
Nenue@14 305 -- Print to Devian output
Nenue@14 306 -- @paramsig tag, ...
Nenue@14 307 -- @param tag channel signature or number used to select console
Nenue@14 308 -- @param ... print arguments
Nenue@0 309 local function Message(prefix, ...)
Nenue@1 310 if prefix == nil then
Nenue@13 311 prefix = 1
Nenue@1 312 end
Nenue@9 313
Nenue@13 314 local channel
Nenue@13 315 local byName = true
Nenue@13 316 if D.sig[prefix] then
Nenue@13 317 channel = D.sig[prefix]
Nenue@13 318 elseif D.console[prefix] then
Nenue@13 319 channel = D.console[prefix]
Nenue@13 320 byName = nil
Nenue@13 321 else
Nenue@13 322 channel = D.console[1]
Nenue@13 323 end
Nenue@9 324 -- color me timbers
Nenue@9 325 local pcolor
Nenue@13 326 if D.tags[prefix] then
Nenue@9 327 pcolor = db.tags[prefix]
Nenue@13 328 elseif byName then
Nenue@0 329 local c = {0, 0, 0 }
Nenue@0 330 local max = string.len(prefix)
Nenue@0 331 for i = 1, max, 3 do
Nenue@0 332 for k, v in ipairs(c) do
Nenue@0 333 local j = i + (k - 1)
Nenue@0 334 c[k] = c[k] + (j <= max and string.byte(prefix,j) or 0)
Nenue@0 335 end
Nenue@0 336 end
Nenue@0 337 for k,v in ipairs(c) do
Nenue@0 338 c[k] = c[k] % 255
Nenue@0 339 if c[k] < 64 then
Nenue@0 340 c[k] = 0
Nenue@0 341 elseif c[k] > 127 then
Nenue@0 342 c[k] = 255
Nenue@0 343 end
Nenue@0 344 end
Nenue@13 345 D.tags[prefix] = string.format('%02X%02X%02X', unpack(c))
Nenue@0 346 end
Nenue@0 347
Nenue@13 348 local buffer = {'|cFF'.. D.tags[prefix]..prefix ..'|r'}
Nenue@0 349 for i = 1, select('#',...) do
Nenue@0 350 local var = select(i, ...)
Nenue@0 351
Nenue@0 352 if type(var) == 'table' then
Nenue@0 353 var = '<table>'
Nenue@0 354 elseif type(var) == 'boolean' then
Nenue@0 355 var = var and 'true' or 'false'
Nenue@0 356 elseif type(var) == 'function' then
Nenue@0 357 var = '<funcref>'
Nenue@0 358 elseif type(var) == 'nil' then
Nenue@0 359 var = 'nil'
Nenue@0 360 end
Nenue@0 361
Nenue@0 362 table.insert(buffer, var)
Nenue@0 363 end
Nenue@13 364 channel.out:AddMessage(table.concat(buffer, ' '))
Nenue@0 365 table.wipe(buffer)
Nenue@0 366 end
Nenue@0 367
Nenue@14 368 -- Spaces each frame evenly across the screen
Nenue@14 369 function D:DistributeFrames() --
Nenue@14 370 print('frame grid:', max, num_side)
Nenue@14 371 local max = self.num_channels
Nenue@14 372 local num_side = math.ceil(math.sqrt(max))
Nenue@14 373 local w = GetScreenWidth() / num_side
Nenue@14 374 local h = GetScreenHeight() / num_side
Nenue@14 375 for i, frame in pairs(D.console) do
Nenue@14 376 local dx = (i-1) % num_side
Nenue@14 377 local dy = math.floor((i-1) / num_side)
Nenue@14 378
Nenue@14 379 print('move:', frame.signature, 'dx=', dx, 'dy=', dy)
Nenue@14 380 print('move:', frame.signature, ' x=', dx * w, 'y=', -(dy * h), 'h=', h, 'w=', w)
Nenue@14 381 frame.width = w
Nenue@14 382 frame.height = h
Nenue@14 383 frame.x = dx * w
Nenue@14 384 frame.y = -(dy * h)
Nenue@14 385 frame:Save()
Nenue@14 386 end
Nenue@14 387
Nenue@14 388 end
Nenue@14 389
Nenue@14 390 -- Place all frames stacked beneath the primary frame
Nenue@14 391 -- @paramsig
Nenue@14 392 function D:StackFrames()
Nenue@14 393 local last
Nenue@14 394 for i, frame in pairs(self.console) do
Nenue@14 395 if last then
Nenue@14 396 frame.x = last.x
Nenue@14 397 frame.y = last.y - 20
Nenue@14 398 else
Nenue@14 399 frame.x = (GetScreenWidth()-frame:GetWidth())/2
Nenue@14 400 frame.y = 0
Nenue@14 401 end
Nenue@14 402 frame:Save()
Nenue@14 403 last = frame
Nenue@14 404 end
Nenue@14 405 end
Nenue@14 406
Nenue@14 407 -- Creates or updates a console frame
Nenue@14 408 -- @paramsig cinfo [, i]
Nenue@14 409 -- @param cinfo an array from db.channels[x] or the desired string signature
Nenue@14 410 -- @param id when set, the console at that index will be assigned all parameters in cinfo
Nenue@14 411 function D:SetChannel(cinfo, i)
Nenue@14 412 print('join:', i , cinfo)
Nenue@14 413 local t_info = {}
Nenue@14 414 if type(cinfo) ~= 'table' then
Nenue@14 415 t_info.signature = tostring(cinfo)
Nenue@14 416 cinfo = {}
Nenue@14 417 end
Nenue@14 418 local srcdb = db.channels[self.primary_channel]
Nenue@14 419 if i ~= nil then
Nenue@14 420 i = tonumber(i)
Nenue@14 421 if db.channels[i] then
Nenue@14 422 print('pull vars from '..db.channels[i].signature)
Nenue@14 423 cinfo = db.channels[i]
Nenue@14 424 srcdb = cinfo
Nenue@14 425 end
Nenue@14 426 end
Nenue@14 427
Nenue@14 428 for k,v in pairs(srcdb) do
Nenue@14 429 if not t_info[k] then
Nenue@14 430 if cinfo[k] then
Nenue@14 431 print('- pulling', k..':',v)
Nenue@14 432 t_info[k] = cinfo[k]
Nenue@14 433 end
Nenue@14 434 end
Nenue@14 435 end
Nenue@14 436
Nenue@14 437 if not db.channels[i] then
Nenue@14 438 t_info.x = t_info.x + 20
Nenue@14 439 t_info.y = t_info.y - 20
Nenue@14 440 db.channels[i] = t_info
Nenue@14 441 end
Nenue@14 442 if not self.console[i] then
Nenue@14 443 self.console[i] = CreateConsole(i, t_info)
Nenue@14 444 end
Nenue@14 445
Nenue@14 446 self.sig[cinfo.signature] = self.console[i]
Nenue@14 447 self.sigID[cinfo.signature] = i
Nenue@14 448 self.IDsig[i] = cinfo.signature
Nenue@14 449 end
Nenue@14 450
Nenue@0 451 function D:OnEnable()
Nenue@13 452 -- commands
Nenue@13 453 local cmdlist = {
Nenue@13 454 ['dvn'] = ScanAddOnList,
Nenue@13 455 ['devian'] = ScanAddOnList,
Nenue@13 456 ['dvc'] = Console_Toggle,
Nenue@13 457 }
Nenue@13 458 for cmd, func in pairs(cmdlist) do
Nenue@13 459 self:RegisterChatCommand(cmd, func, true)
Nenue@13 460 end
Nenue@13 461
Nenue@11 462 if db.enabled == true then
Nenue@0 463 D:Print('Standard AddOn list active. Type /dvn to switch to development mode.')
Nenue@0 464 else
Nenue@0 465 D:Print('Development AddOn list active. Type /dvn to revert to regular operation.')
Nenue@0 466 end
Nenue@13 467
Nenue@0 468 end
Nenue@0 469
Nenue@0 470 function D:OnInitialize()
Nenue@13 471 -- emergency button
Nenue@13 472 self:RegisterChatCommand("cleandvn", function(args)
Nenue@13 473 DevianDB = nil
Nenue@13 474 ReloadUI()
Nenue@13 475 end)
Nenue@13 476
Nenue@13 477 -- savedvars
Nenue@13 478 local cherry = false
Nenue@9 479 if not _G.DevianDB then
Nenue@13 480 _G.DevianDB = defaults
Nenue@13 481 cherry = "Type /dvnsave to snapshot your current UI"
Nenue@9 482 end
Nenue@9 483 db = _G.DevianDB
Nenue@0 484
Nenue@0 485 if not db[PLAYER_REALM] then
Nenue@9 486 db[PLAYER_REALM] = {[STATE_LOW] = {}, [STATE_HIGH] = {}}
Nenue@0 487 if not cherry then
Nenue@0 488 cherry = "This character didn't have an AddOn table."
Nenue@0 489 end
Nenue@0 490 end
Nenue@0 491
Nenue@13 492 -- copy tags
Nenue@13 493 self.tags = {}
Nenue@13 494 for n, c in pairs(db.tags) do
Nenue@13 495 self.tags[n] = c
Nenue@13 496 end
Nenue@0 497 if cherry then
Nenue@0 498 D:Print(cherry)
Nenue@0 499 end
Nenue@0 500 D.oldprint = getprinthandler()
Nenue@0 501 if not _G.oldprint then
Nenue@0 502 _G.oldprint = D.oldprint
Nenue@0 503 end
Nenue@13 504
Nenue@14 505 self.raise_ct = 0
Nenue@14 506 self.last_channel = 0
Nenue@14 507 self.num_channels = 0
Nenue@13 508 self.console = {}
Nenue@13 509 self.sig = {}
Nenue@14 510 self.sigID = {}
Nenue@14 511 self.IDsig = {}
Nenue@14 512 for i, cinfo in pairs(db.channels) do
Nenue@14 513 i = tonumber(i)
Nenue@14 514 if not self.primary_channel then
Nenue@14 515 self.primary_channel = i
Nenue@14 516 end
Nenue@14 517 self:SetChannel(cinfo, i)
Nenue@14 518 if i > self.last_channel then
Nenue@14 519 self.last_channel = i
Nenue@14 520 end
Nenue@14 521 self.num_channels = self.num_channels + 1
Nenue@13 522 end
Nenue@0 523 setprinthandler(Message)
Nenue@13 524 print(MAJOR, MINOR)
Nenue@0 525 end