Skip to content

Instantly share code, notes, and snippets.

@sylvanaar
Last active July 2, 2020 16:30
Show Gist options
  • Save sylvanaar/aea7516e23ad0706cf1f7c19f4d34515 to your computer and use it in GitHub Desktop.
Save sylvanaar/aea7516e23ad0706cf1f7c19f4d34515 to your computer and use it in GitHub Desktop.
Idea for a library to handle addon output in a cleaner way
local lib, oldminor = LibStub:NewLibrary("LibChatTypes-1.0", 1)
if not lib then return end
local registry = {}
local emitterproto = {}
local function dbg(...)
--Prat:PrintLiteral(...)
end
local function createTypeEmitter(t, type)
return function(self, text) self:Output(text) end
end
function emitterproto:Output(type, text, ...)
local chattype = "ADDON_" .. self.key .. (type ~= nil and ("_" .. type) or "")
local event = "CHAT_MSG_" .. chattype
local i = 1
local frame = _G['ChatFrame' .. i]
while frame do
if tContains(frame.messageTypeList, chattype) then
ChatFrame_MessageEventHandler(frame, event, text, '', '', '', '', '')
end
i = i + 1
frame = _G['ChatFrame' .. i]
end
end
-- We allow for 2 sources of names, GetAddonName(), and LibStub()'s list of libraries
-- register basically tells this library that it should set up the chat types and create the pring
-- handler for the given soure
-- Call with :Register("Prat-3.0")
function lib:Register(name, ...)
if select(2, GetAddOnInfo(name)) == nil and LibStub:GetLibrary(name, true) == nil then
-- Trying to register invalid name should be and addon name or library name
end
local key = name:upper()
if registry[key] then
return registry[key]
end
local emitter = { key = key }
registry[key] = emitter
local baseEvent = "CHAT_MSG_ADDON_" .. key
local baseType = "ADDON_" .. key
-- Configure default formatting
_G["CHAT_" .. baseType .. "_GET"] = ""
ChatTypeInfo[baseType] = CopyTable(ChatTypeInfo["SAY"])
local types = { ... }
local group = { baseEvent }
-- Add the chat type
ChatTypeGroup[baseType] = group
for i, v in ipairs(types) do
group[#group + 1] = baseEvent .. "_" .. v
end
-- Add a category for all addon messages
local category = CHAT_CATEGORY_LIST["ADDON"] or {}
tinsert(category, baseType)
CHAT_CATEGORY_LIST["ADDON"] = category
-- Add an option to control the output of the message
CHAT_CONFIG_CHAT_LEFT[#CHAT_CONFIG_CHAT_LEFT + 1] = {
type = baseType,
text = "Addon: " .. name,
checked = function() return IsListeningForMessageType(baseType); end;
func = function(self, checked) ToggleChatMessageGroup(checked, baseType); end;
}
ChatFrame_AddMessageGroup(ChatFrame1, baseType)
ChatConfig_CreateCheckboxes(ChatConfigChatSettingsLeft, CHAT_CONFIG_CHAT_LEFT, "ChatConfigWideCheckBoxWithSwatchTemplate", PLAYER_MESSAGES);
ChatConfig_UpdateCheckboxes(ChatConfigChatSettingsLeft);
emitter.types = types
setmetatable(emitter, {
__index = function(t, k)
if emitterproto[k] then return emitterproto[k] end
if type(t.types) == "table" then
return createTypeEmitter(t, k)
end
end,
__call = function(t, ...)
t:Output(nil, ...)
end
})
return emitter
end
function lib:ReplaceChatFrameFunctions()
function ChatFrame_RegisterForMessages(self, ...)
local messageGroup;
local index = 1;
for i = 1, select("#", ...) do
messageGroup = ChatTypeGroup[select(i, ...)];
if (messageGroup) then
self.messageTypeList[index] = select(i, ...);
for index, value in pairs(messageGroup) do
if not value:match("CHAT_MSG_ADDON_.+") then
self:RegisterEvent(value);
end
end
index = index + 1;
end
end
end
function ChatFrame_AddMessageGroup(chatFrame, group)
local info = ChatTypeGroup[group];
if (info) then
tinsert(chatFrame.messageTypeList, group);
for index, value in pairs(info) do
if not value:match("CHAT_MSG_ADDON_.+") then
chatFrame:RegisterEvent(value);
end
end
AddChatWindowMessages(chatFrame:GetID(), group);
end
end
function ChatFrame_AddSingleMessageType(chatFrame, messageType)
local group = ChatTypeGroupInverted[messageType];
local info = ChatTypeGroup[group];
if (info) then
if (not tContains(chatFrame.messageTypeList, group)) then
tinsert(chatFrame.messageTypeList, group);
end
for index, value in pairs(info) do
if (value == messageType) and not value:match("CHAT_MSG_ADDON_.+") then
chatFrame:RegisterEvent(value);
end
end
end
end
function ChatFrame_RemoveMessageGroup(chatFrame, group)
local info = ChatTypeGroup[group];
if (info) then
for index, value in pairs(chatFrame.messageTypeList) do
if (strupper(value) == strupper(group)) then
chatFrame.messageTypeList[index] = nil;
end
end
for index, value in pairs(info) do
if not value:match("CHAT_MSG_ADDON_.+") then
chatFrame:UnregisterEvent(value);
end
end
RemoveChatWindowMessages(chatFrame:GetID(), group);
end
end
function ChatFrame_RemoveAllMessageGroups(chatFrame)
for index, value in pairs(chatFrame.messageTypeList) do
for eventIndex, eventValue in pairs(ChatTypeGroup[value]) do
if not eventValue:match("CHAT_MSG_ADDON_.+") then
chatFrame:UnregisterEvent(eventValue);
end
end
RemoveChatWindowMessages(chatFrame:GetID(), value);
end
chatFrame.messageTypeList = {};
end
end
lib:ReplaceChatFrameFunctions()
@sylvanaar
Copy link
Author

sylvanaar commented Jun 30, 2020

So if I run it with Prat's module that shows the event type for each message i get:

[00:23:31] Prat 3.0: >> print(LibStub("LibChatTypes-1.0"):Register("Prat-3.0")("test"))
[00:23:31] test  (CHAT_MSG_ADDON_PRAT-3.0)

Also it has set up

[00:32:05] Prat 3.0: >> print(ChatTypeGroup["ADDON_PRAT-3.0"])
[00:32:05] Prat 3.0: { "CHAT_MSG_ADDON_PRAT-3.0" }

and

[00:32:51] Prat 3.0: >> print(CHAT_CATEGORY_LIST["ADDON"])
[00:32:51] Prat 3.0: { "ADDON_PRAT-3.0" }

@sylvanaar
Copy link
Author

image

@KyrosKrane
Copy link

Two thoughts:

  1. I don't know if it's possible, but organizationally, it would make sense to have a category in the left hand column called Addons, and then list all addons under that with just their name.

  2. This would be most useful for addons that have a lot of chat output. The big one that comes to mind is DBM, but perhaps some of the roleplay-type addons could also benefit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment