You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

717 lines
22 KiB

--[[ BEGIN STANDARD HEADER ]] --
-- Imports
local _G = _G
local LibStub = LibStub
local setmetatable = setmetatable
local pairs, ipairs = pairs, ipairs
local tinsert, tremove, tconcat = table.insert, table.remove, table.concat
local string = string
local strsub = string.sub
local strsplit = strsplit
local tonumber, tostring = tonumber, tostring
local strlower, strupper = strlower, strupper
local strlen = strlen
local type = type
local next, wipe = next, wipe
local select = select
--local function RunOldMessageEventFilters(event, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12)
-- local filter = false
-- local chatFilters = _G.ChatFrame_GetMessageEventFilters and _G.ChatFrame_GetMessageEventFilters(event)
-- local newarg1 = arg1
--
-- if chatFilters then
-- for _, filterFunc in next, chatFilters do
-- filter, newarg1 = filterFunc(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12)
-- if filter then
-- return true
-- end
-- arg1 = newarg1 or arg1
-- end
-- end
--
-- return filter, arg1
--end
-- arg1, filterthisout = RunMessageEventFilters(event, arg1)
local newarg1, newarg2, newarg3, newarg4, newarg5, newarg6, newarg7, newarg8, newarg9, newarg10, newarg11, newarg12, newarg13, newrg14, newarg15, newarg16, newarg17
local function RunMessageEventFilters(frame, event, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17)
local filter = false
local chatFilters = _G.ChatFrame_GetMessageEventFilters and _G.ChatFrame_GetMessageEventFilters(event)
if chatFilters then
for _, filterFunc in next, chatFilters do
if filterFunc ~= MessageEventFilter then
filter, newarg1, newarg2, newarg3, newarg4, newarg5, newarg6, newarg7, newarg8, newarg9, newarg10, newarg11, newarg12, newarg13, newrg14, newarg15, newarg16, newarg17 =
filterFunc(frame, event, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17)
if filter then
return true
elseif (newarg1) then
arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17 =
newarg1, newarg2, newarg3, newarg4, newarg5, newarg6, newarg7, newarg8, newarg9, newarg10, newarg11, newarg12, newarg13, newrg14, newarg15, newarg16, newarg17
end
end
end
end
return filter, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17
end
-- Isolate the environment
setfenv(1, select(2, ...))
--[[ END STANDARD HEADER ]] --
-- This is the structure of the chat message once it is split
-- section delimiters are uppercase inside and lower case outside
-- ie. cC CHANNEL Cc = [ channame ]
SplitMessageSrc = {
-- todo, incidicate which module uses which field, and remove unused fields
PRE = "",
nN = "",
CHANLINK = "",
NN = "",
cC = "",
CHANNELNUM = "",
CC = "",
CHANNEL = "",
zZ = "",
ZONE = "",
Zz = "",
Cc = "",
TYPEPREFIX = "",
Nn = "",
fF = "",
FLAG = "",
Ff = "",
pP = "",
lL = "", -- link start
PLAYERLINK = "",
PLAYERLINKDATA = "",
LL = "", -- link text start
PLAYER = "",
NONPLAYER = "",
sS = "",
SERVER = "",
Ss = "",
Ll = "", -- link text end
Pp = "",
TYPEPOSTFIX = "",
mM = "",
gG = "",
LANGUAGE = "",
Gg = "",
MOBILE = "",
MESSAGE = "",
Mm = "",
POST = "",
}
SplitMessageIdx = {
"PRE",
"nN",
"CHANLINK",
"NN",
"cC",
"CHANNELNUM",
"CC",
"CHANNEL",
-- Zone is not usually included
-- "zZ",
-- "ZONE",
-- "Zz",
"Cc",
"TYPEPREFIX",
"Nn",
"fF",
"FLAG",
"Ff",
"pP",
"TIMERUNNER",
"lL",
"PLAYERLINK",
"PLAYERLINKDATA",
"LL",
"PLAYER",
"NONPLAYER",
"sS",
"SERVER",
"Ss",
"Ll",
"Pp",
"TYPEPOSTFIX",
"mM",
"gG",
"LANGUAGE",
"Gg",
"MOBILE",
"MESSAGE",
"Mm",
"POST",
}
SplitMessage = {}
SplitMessageOrg = {}
SplitMessageOut = {
MESSAGE = "",
TYPE = "",
TARGET = "",
CHANNEL = "",
LANGUAGE = "",
}
setmetatable(SplitMessageOrg, {
__index = SplitMessageSrc
})
setmetatable(SplitMessage, {
__index = SplitMessageOrg
})
do
local t = {}
function BuildChatText(message, index)
local index = index or SplitMessageIdx --todo
local s = message
for k in pairs(t) do
t[k] = nil
end
for i, v in ipairs(index) do
tinsert(t, s[v])
end
return tconcat(t, "")
end
end
function RegisterMessageItem(itemname, anchorvar, relativepos)
--[[ RegisterMessageItem:
API to allow other modules to inject new items into the components
making up a chat message. Primarily intended to help resolve
conflicts between modules.
- itemname = name of the variable to be injected
- aftervar = the position in the chat message after which the item
will be displayed
- relativepos = "before" or "after"
Leave aftervar blank to position the item at the beginning of the list.
If you would like to change the item's position in the chat message,
call :RegisterMessageItem() again with a different value for aftervar.
Example:
--------
The mod Prat_ExampleMod counts the number of times people
say the word "Example" and you would like to display the count
for a player before their name in a chat message. Default chat
message structure contains:
... cC CHANNEL Cc .. pP PLAYER Pp ...
This means that the module should use the following:
RegisterMessageItem('NUMEXAMPLES', 'Cc')
Which would then alter the structure of chat messages to be:
.. CHANNEL Cc .. NUMEXAMPLES .. pP PLAYER ...
]]
local pos = 1
if SplitMessageSrc[itemname] then
-- ResetSeparators(itemname)
local oldpos = GetMessageItemIdx(itemname)
if oldpos ~= 0 then
tremove(SplitMessageIdx, oldpos)
end
end
if anchorvar then
pos = GetMessageItemIdx(anchorvar) + (relativepos == "before" and 0 or 1)
end
tinsert(SplitMessageIdx, pos, itemname)
SplitMessageSrc[itemname] = ""
end
function GetMessageItemIdx(itemname)
for i, v in ipairs(SplitMessageIdx) do
if v == itemname then
return i
end
end
return 0
end
function ClearChatSections(message)
wipe(message)
end
local function safestr(s) return s or "" end
function SplitChatMessage(frame, event, ...)
local arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17 = ...
if (strsub((event or ""), 1, 8) == "CHAT_MSG") then
local type = strsub(event, 10)
if (arg16) then
-- hiding sender in letterbox: do NOT even show in chat window (only shows in cinematic frame)
return true;
end
local info
local channelLength = arg4 and strlen(arg4) or 0
local infoType = type;
if ( (type == "COMMUNITIES_CHANNEL") or ((strsub(type, 1, 7) == "CHANNEL") and (type ~= "CHANNEL_LIST") and ((arg1 ~= "INVITE") or (type ~= "CHANNEL_NOTICE_USER"))) ) then
local found = 0;
for index, value in pairs(frame.channelList) do
if ( channelLength > strlen(value) ) then
-- arg9 is the channel name without the number in front...
if ( ((arg7 > 0) and (frame.zoneChannelList[index] == arg7)) or (strupper(value) == strupper(arg9)) ) then
found = 1;
infoType = "CHANNEL"..arg8;
info = _G.ChatTypeInfo[infoType];
break;
end
end
end
if ( (found == 0) or not info ) then
return true;
end
end
ClearChatSections(SplitMessageOrg)
ClearChatSections(SplitMessage)
local s = SplitMessageOrg
s.LINE_ID = arg11
s.INFOTYPE = infoType
info = _G.ChatTypeInfo[infoType]
-- blizzard bug, arg2 (player name) can have an extra space
if arg2 then
arg2 = arg2:trim()
end
s.GUID = arg12
s.ARGS = {
...
}
--[==[@debug@
if CHAT_PLAYER_GUIDS then
if s.GUID and s.GUID:len() > 0 and s.GUID ~= "0000000000000000" and s.GUID ~= "0x0300000000000000" then
s.GUIDINFO = {
_G.GetPlayerInfoByGUID(s.GUID)
}
end
end
s.FRAME = frame and frame:GetName()
--@end-debug@]==]
-- if NEW_CHATFILTERS then
local kill, newarg1, newarg2, newarg3, newarg4, newarg5, newarg6, newarg7, newarg8, newarg9, newarg10, newarg11, newarg12, newarg13, newarg14 =
RunMessageEventFilters(frame, event, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14)
if kill then
return true
end
if newarg1 ~= nil then
arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14 =
newarg1, newarg2, newarg3, newarg4, newarg5, newarg6, newarg7, newarg8, newarg9, newarg10, newarg11, newarg12, newarg13, newarg14
end
-- else
-- local kill, newarg1 = RunOldMessageEventFilters(event, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12)
-- if kill then
-- return true
-- end
--
-- arg1 = newarg1 or arg1
-- end
s.CHATTYPE = type
s.EVENT = event
local chatGroup = _G.Chat_GetChatCategory(type)
s.CHATGROUP = chatGroup
local chatTarget;
local presenceID
if (chatGroup == "CHANNEL" or chatGroup == "BN_CONVERSATION") then
chatTarget = tostring(arg8);
elseif (chatGroup == "WHISPER" or chatGroup == "BN_WHISPER") then
if (not (strsub(arg2, 1, 2) == "|K")) then
chatTarget = strupper(arg2);
else
chatTarget = arg2;
end
end
s.CHATTARGET = chatTarget
s.MESSAGE = safestr(arg1):gsub("^%s*(.-)%s*$", "%1") -- trim spaces
if (_G.FCFManager_ShouldSuppressMessage(frame, s.CHATGROUP, s.CHATTARGET)) then
s.DONOTPROCESS = true
end
if (chatGroup == "WHISPER" or chatGroup == "BN_WHISPER") then
if (frame.privateMessageList and not frame.privateMessageList[strlower(arg2)]) then
s.DONOTPROCESS = true
elseif (frame.excludePrivateMessageList and frame.excludePrivateMessageList[strlower(arg2)]) then
s.DONOTPROCESS = true
end
elseif (chatGroup == "BN_CONVERSATION") then
if (frame.bnConversationList and not frame.bnConversationList[arg8]) then
s.DONOTPROCESS = true
elseif (frame.excludeBNConversationList and frame.excludeBNConversationList[arg8]) then
s.DONOTPROCESS = true
end
end
local chatget = _G["CHAT_" .. type .. "_GET"]
if chatget then
local chatlink = chatget:match("|H(channel:[^|]-)|h[^|]-|h")
if chatlink then
s.CHANLINK = chatlink
s.nN = "|H"
s.NN = "|h"
s.Nn = "|h"
chatget = chatget:gsub("|Hchannel:[^|]-|h([^|]-)|h", "%1")
end
s.TYPEPREFIX, s.TYPEPOSTFIX = string.match(chatget, "(.*)%%s(.*)")
end
s.TYPEPOSTFIX = safestr(s.TYPEPOSTFIX)
s.TYPEPREFIX = safestr(s.TYPEPREFIX)
local arg2 = safestr(arg2)
if strlen(arg2) > 0 then
if (strsub(type, 1, 7) == "MONSTER" or type == "RAID_BOSS_EMOTE" or
type == "CHANNEL_NOTICE" or type == "CHANNEL_NOTICE_USER") then
-- no link
s.NONPLAYER = arg2
elseif type == "EMOTE" then
s.PLAYER = _G.Ambiguate(arg2, "none"):match("([^%-]+)%-?(.*)")
elseif type == "TEXT_EMOTE" then
else
s.PLAYERLINK = arg2
--ambiguate guild chat names
if (type == "GUILD") then
arg2 = _G.Ambiguate(arg2, "guild")
else
arg2 = _G.Ambiguate(arg2, "none")
end
local plr, svr = arg2:match("([^%-]+)%-?(.*)")
s.pP = "["
s.lL = "|Hplayer:"
s.LL = "|h"
s.PLAYER = plr
if svr and strlen(svr) > 0 then
s.sS = "-"
s.SERVER = svr
end
s.Ll = "|h"
s.Pp = "]"
local playerLinkDisplayText = s.pP .. s.PLAYER .. s.Pp
local isCommunityType = type == "COMMUNITIES_CHANNEL";
local playerName, lineID, bnetIDAccount = arg2, arg11, arg13;
if (isCommunityType) then
-- local isBattleNetCommunity = bnetIDAccount ~= nil and bnetIDAccount ~= 0;
-- local messageInfo, clubId, streamId, clubType = _G.C_Club.GetInfoFromLastCommunityChatLine();
-- if (messageInfo ~= nil) then
-- if ( isBattleNetCommunity ) then
-- playerLink = _G.GetBNPlayerCommunityLink(playerName, playerLinkDisplayText, bnetIDAccount, clubId, streamId, messageInfo.messageId.epoch, messageInfo.messageId.position);
-- else
-- playerLink = _G.GetPlayerCommunityLink(playerName, playerLinkDisplayText, clubId, streamId, messageInfo.messageId.epoch, messageInfo.messageId.position);
-- end
-- else
-- playerLink = playerLinkDisplayText;
-- end
else
if (type ~= "BN_WHISPER" and type ~= "BN_WHISPER_INFORM" and type ~= "BN_CONVERSATION") or arg2 == _G.UnitName("player") --[[or presenceID]] then
s.PLAYERLINKDATA = ":" .. safestr(arg11) .. ":" .. chatGroup .. (chatTarget and (":" .. chatTarget) or "")
else
s.lL = "|HBNplayer:"
local battleTag, _
if _G.C_BattleNet and _G.C_BattleNet.GetAccountInfoByID then
battleTag = _G.C_BattleNet.GetAccountInfoByID(arg13).battleTag
else
_, _, battleTag = _G. BNGetFriendInfoByID(arg13)
end
s.PLAYERLINKDATA = ":" .. safestr(arg13) .. ":" .. safestr(arg11) .. ":" .. chatGroup .. ":" .. chatTarget .. (battleTag and (":" .. battleTag) or "")
s.PRESENCE_ID = arg13
end
end
end
end
-- If we are handling notices, format them like bliz
if (type == "CHANNEL_NOTICE_USER") then
s.NOTICE = arg1
local globalstring = _G["CHAT_" .. arg1 .. "_NOTICE_BN"];
local chatnotice
if globalstring then
chatnotice = globalstring:gsub("|Hchannel:CHANNEL[^|]-|h[^|]-|h", ""):trim();
else
globalstring = _G["CHAT_" .. arg1 .. "_NOTICE"];
chatnotice = globalstring:gsub("|Hchannel:[^|]-|h[^|]-|h", ""):trim()
end
if strlen(arg5) > 0 then
-- TWO users in this notice (E.G. x kicked y)
if _G.GetLocale() == "koKR" then
s.MESSAGE = chatnotice:format("", "", arg2, arg5)
else
s.MESSAGE = chatnotice:format(arg2, arg5)
end
elseif (arg1 == "INVITE") then
s.MESSAGE = chatnotice:format(arg4, arg2)
else
s.MESSAGE = chatnotice:format(arg2)
end
elseif type == "CHANNEL_NOTICE" then
local globalstring;
s.NOTICE = arg1
if ( arg1 == "TRIAL_RESTRICTED" ) then
globalstring = _G.CHAT_TRIAL_RESTRICTED_NOTICE_TRIAL;
else
globalstring = _G["CHAT_"..arg1.."_NOTICE_BN"];
if ( not globalstring ) then
globalstring = _G["CHAT_"..arg1.."_NOTICE"];
if not globalstring then
_G.GMError(("Missing global string for %q"):format("CHAT_"..arg1.."_NOTICE"));
return;
end
end
end
s.MESSAGE = _G.format(globalstring, arg8, _G.ChatFrame_ResolvePrefixedChannelName(arg4))
end
local arg6 = safestr(arg6)
if strlen(arg6) > 0 then
s.fF = ""
if arg6 == "GM" or arg6 == "DEV" then
-- Add Blizzard Icon if this was sent by a GM/DEV
s.FLAG = "|TInterface\\ChatFrame\\UI-ChatIcon-Blizz:12:20:0:0:32:16:4:28:0:16|t "
elseif arg6 == "GUIDE" and _G.ChatFrame_GetMentorChannelStatus(_G.Enum.PlayerMentorshipStatus.Mentor, _G.C_ChatInfo.GetChannelRulesetForChannelID(arg7)) == _G.Enum.PlayerMentorshipStatus.Mentor then
-- Add guide text if the sender is a guide in the newcomer chat
s.FLAG = _G.NPEV2_CHAT_USER_TAG_GUIDE .. " "
elseif arg6 == "NEWCOMER" then
if _G.ChatFrame_GetMentorChannelStatus(_G.Enum.PlayerMentorshipStatus.Newcomer, _G.C_ChatInfo.GetChannelRulesetForChannelID(arg7)) == _G.Enum.PlayerMentorshipStatus.Newcomer then
-- Add murloc icon for messages from new players in the newcomer chat
s.FLAG = _G.NPEV2_CHAT_USER_TAG_NEWCOMER
end
else
s.FLAG = _G["CHAT_FLAG_" .. arg6]
end
s.Ff = ""
end
if arg12 and _G.C_ChatInfo.IsTimerunningPlayer and _G.C_ChatInfo.IsTimerunningPlayer(arg12) then
s.TIMERUNNER = _G.CreateAtlasMarkup("timerunning-glues-icon", 12, 12)
else
s.TIMERUNNER = ""
end
if arg15 then
s.MOBILE = _G.ChatFrame_GetMobileEmbeddedTexture(info.r, info.g, info.b)
end
local arg3 = safestr(arg3)
if ((strlen(arg3) > 0) and (arg3 ~= "Universal") and (arg3 ~= frame.defaultLanguage)) then
s.gG = "["
s.LANGUAGE = arg3
s.Gg = "] "
else
s.LANGUAGE_NOSHOW = arg3
end
local arg9 = safestr(arg9)
if strlen(arg9) > 0 or chatGroup == "BN_CONVERSATION" then
-- local bracket, post_bracket = string.match(s.TYPEPREFIX, "%[(.*)%](.*)")
-- bracket = safestr(bracket)
-- if strlen(bracket) > 0 then
-- s.cC = "["
-- s.Cc = "]"
-- s.CHANNEL = bracket
-- s.TYPEPREFIX = safestr(post_bracket)
-- end
if strlen(safestr(arg8)) > 0 and arg8 > 0 then
s.CC = ". "
s.nN = "|H"
s.NN = "|h"
s.Nn = "|h"
if chatGroup == "BN_CONVERSATION" then
s.CHANLINK = "channel:BN_CONVERSATION:" .. arg8
else
s.CHANNELNUM = tostring(arg8)
s.CHANLINK = "channel:channel:" .. tostring(arg8)
end
end
if chatGroup == "BN_CONVERSATION" then
s.cC = "["
s.Cc = "] "
s.CHANNELNUM = tostring(_G.MAX_WOW_CHAT_CHANNELS + arg8)
s.CHANNEL = _G.CHAT_BN_CONVERSATION_SEND:match("%[%%d%. (.*)%]")
elseif arg7 > 0 then
s.cC = "["
s.Cc = "] "
s.CHANNEL, s.zZ, s.ZONE = string.match(arg9, "(.*)(%s%-%s)(.*)")
if s.CHANNEL:len() == 0 then
s.CHANNEL = arg9
end
s.CHANNEL = safestr(s.CHANNEL)
s.zZ = safestr(s.zZ)
s.ZONE = safestr(s.ZONE)
s.Zz = ""
elseif chatGroup == "COMMUNITIES_CHANNEL" then
s.cC = "["
s.Cc = "] "
s.CHANNEL = _G.ChatFrame_ResolvePrefixedChannelName(arg4):match("%d%.%s+(.+)")
else
if strlen(arg9) > 0 then
s.CHANNEL = arg9
s.cC = "["
s.Cc = "] "
end
end
end
-- local _, fontHeight = _G.GetChatWindowInfo(frame:GetID());
--
-- if ( fontHeight == 0 ) then
-- --fontHeight will be 0 if it's still at the default (14)
-- fontHeight = 14;
-- end
local arg7 = tonumber(arg7)
-- 2.4
-- Search for icon links and replace them with texture links.
local term;
for tag in string.gmatch(arg1, "%b{}") do
term = strlower(string.gsub(tag, "[{}]", ""));
if (not arg17 and _G.ICON_TAG_LIST[term] and _G.ICON_LIST[_G.ICON_TAG_LIST[term]]) then
s.MESSAGE = string.gsub(s.MESSAGE, tag, _G.ICON_LIST[_G.ICON_TAG_LIST[term]] .. "0|t");
--
-- This would allow for ignoring unknown icon tags
--
-- else
-- s.MESSAGE = string.gsub(s.MESSAGE, tag, "");
elseif (_G.GROUP_TAG_LIST[term]) then
local groupIndex = _G.GROUP_TAG_LIST[term];
local groupList = "[";
for i = 1, _G.GetNumGroupMembers() do
local name, rank, subgroup, level, class, classFileName = _G.GetRaidRosterInfo(i);
if (name and subgroup == groupIndex) then
local t = _G.RAID_CLASS_COLORS[classFileName];
name = string.format("\124cff%.2x%.2x%.2x%s\124r", t.r * 255, t.g * 255, t.b * 255, name);
groupList = groupList .. (groupList == "[" and "" or _G.PLAYER_LIST_DELIMITER) .. name;
end
end
groupList = groupList .. "]";
s.MESSAGE = string.gsub(s.MESSAGE, tag, groupList);
end
end
if type == "SYSTEM" or strsub(type, 1, 11) == "ACHIEVEMENT" or strsub(type, 1, 11) == "TARGETICONS" or strsub(type, 1, 18) == "GUILD_ACHIEVEMENT" then
if strsub(type, 1, 11) == "ACHIEVEMENT" or strsub(type, 1, 18) == "GUILD_ACHIEVEMENT" then
s.MESSAGE = s.MESSAGE:format("")
end
local pl, p, rest = string.match(s.MESSAGE, "|Hplayer:(.-)|h%[(.-)%]|h(.+)")
if pl and p then
local plr, svr = pl:match("([^%-]+)%-?(.*)")
s.pP = "["
s.lL = "|Hplayer:"
s.PLAYERLINK = pl
s.LL = "|h"
s.PLAYER = plr
s.Ll = "|h"
s.Pp = "]"
s.MESSAGE = rest
if svr and strlen(svr) > 0 then
s.sS = "-"
s.SERVER = svr
end
if arg11 then
s.PLAYERLINKDATA = ":" .. safestr(arg11)
end
end
end
s.ACCESSID = _G.ChatHistory_GetAccessID(chatGroup, chatTarget);
s.TYPEID = _G.ChatHistory_GetAccessID(type, chatTarget, arg12 or arg13);
SplitMessage.ORG = SplitMessageOrg
s.INFO = info
return SplitMessage, info
end
end