Quantcast
WoWInterface - View Single Post - Code optimization and issue with hyperlinks in chat
View Single Post
01-08-19, 02:59 PM   #16
Terenna
A Flamescale Wyrmkin
AddOn Author - Click to view addons
Join Date: Jun 2016
Posts: 105
hey jlam, thanks for the advice

I was able to rewrite the code to look like
Lua Code:
  1. local letterTable, coloredMessage, holder, placeHolderWord = {}, {} --letterTable will be used to hold our individual words free from any punctuation or numbers, coloredMessage is ultimately what we will return, holder is used to find strings of letters and insert them into our letterTable, placeHolderWord is so we can perform a final gsub at the end
  2. local function hexColorNames(chatMessage, modChatColor)
  3.     wipe(coloredMessage) --blizzard function that will clear our table
  4.     for word in gmatch(chatMessage, '%S+') do --look at each word individually, separating them by spaces (we look for non-whitespace)
  5.         placeHolderWord = word
  6.         local _
  7.         local class, name, coloredName = nil, nil, nil
  8.         wipe(letterTable) --wipe our letterTable from any previous entries
  9.         while strfind(placeHolderWord, '%a') do --we're going to be removing all blocks of letters from our word
  10.             holder = placeHolderWord:match('[^%p%s%d]+') --extract our blocks of letters, we don't want numbers, spaces, or punctuation, (we use this instead of [%a]+ because it allows for non-ascii characters
  11.             if holder then --safety so we don't throw an error inserting nil into a table
  12.                 table.insert(letterTable, holder) --put our letter block into our letterTable holder
  13.                 placeHolderWord = placeHolderWord:gsub(holder, '') --names can ultimately be a simple name from your realm, a name with
  14.             end
  15.         end
  16.        
  17.         if (#letterTable == 1 and letterTable[1]:lower() ~= 'player' and letterTable[1]:lower() ~= 'target' and letterTable[1]:lower() ~= 'focus') then --our table is only 1 entry long, and therefore it can't be someone on another realm
  18.             name = letterTable[1]
  19.             _, class = UnitClass(letterTable[1])
  20.         elseif #letterTable == 2 then
  21.             if strfind(word, 'Area52') then
  22.                 name = letterTable[1]..'%-'..letterTable[2]..'52' --we use the % so we can gsub; the '52' won't be transferred to letterTable as it specifically excludes numbers, this is a shitty hack for people on Area 52
  23.                 _, class = UnitClass(letterTable[1]..'-'..letterTable[2]..'52')
  24.             else
  25.                 name = letterTable[1]..'%-'..letterTable[2] --we use the % so we can gsub
  26.                 _, class = UnitClass(letterTable[1]..'-'..letterTable[2])
  27.             end
  28.         elseif #letterTable >= 3 then --we use >= rather than == incase someone adds letters afterwards to try and catch more names this way
  29.             name = letterTable[1]..'%-'..letterTable[2].."%'"..letterTable[3] --we use the % in front of the magic characters so we can gsub
  30.             _, class = UnitClass(letterTable[1]..'-'..letterTable[2].."'"..letterTable[3])
  31.         end
  32.        
  33.         if (class and class ~= '') then --if we actually got a class and it's not '' then we can modify the text to have class color and return back to the text color before it
  34.             coloredName = '|c'..RAID_CLASS_COLORS[class or class:gsub(' ', '')].colorStr..name..modChatColor
  35.             word = word:gsub(name, coloredName)
  36.         end
  37.        
  38.         table.insert(coloredMessage, word)
  39.     end
  40.    
  41.     return(table.concat(coloredMessage, ' '))
  42. end

and
Lua Code:
  1. local function modHexColorNames(chatMessage, modChatColor) --differs from hexColorNames because it class colors 'You' and 'you' and 'Your' and 'your' and removes realmNames from players
  2.     wipe(coloredMessage) --blizzard function that will clear our table
  3.     for word in gmatch(chatMessage, '%S+') do --look at each word individually, separating them by spaces (we look for non-whitespace)
  4.         placeHolderWord = word
  5.         local _
  6.         local class, name, coloredName = nil, nil, nil
  7.         wipe(letterTable) --wipe our letterTable from any previous entries
  8.         while strfind(placeHolderWord, '%a') do --we're going to be removing all blocks of letters from our word
  9.             holder = placeHolderWord:match('[^%p%s%d]+') --extract our blocks of letters, we don't want numbers, spaces, or punctuation, (we use this instead of [%a]+ because it allows for non-ascii characters
  10.             if holder then --safety so we don't throw an error inserting nil into a table
  11.                 table.insert(letterTable, holder) --put our letter block into our letterTable holder
  12.                 placeHolderWord = placeHolderWord:gsub(holder, '') --names can ultimately be a simple name from your realm, a name with
  13.             end
  14.         end
  15.        
  16.         for i = 1, 3 do
  17.             if (i == 1 and letterTable[i]) then --the potential name doesn't have a realm
  18.                 _, class = UnitClass(letterTable[1])
  19.                 if class and class ~= '' then break end
  20.             elseif (i == 2 and letterTable[i]) then --the potential name has at least a realm name
  21.                 if strfind(word, 'Area52') then --hack because our match specifically avoids numbers, Area 52 is the only realm with numbers
  22.                     _, class = UnitClass(letterTable[1]..'-'..letterTable[2]..'52')
  23.                     if class and class ~= '' then break end
  24.                 else
  25.                     _, class = UnitClass(letterTable[1]..'-'..letterTable[2])
  26.                     if class and class ~= '' then break end
  27.                 end
  28.             elseif (i == 3 and letterTable[i]) then --the potential name might have a realm and an ' in the realmName
  29.                 _, class = UnitClass(letterTable[1]..'-'..letterTable[2].."'"..letterTable[3])
  30.             end
  31.         end
  32.                
  33.         if (class and class ~= '') then --if we actually got a class and it's not '' then we can modify the text to have class color and return back to the text color before it
  34.             if #letterTable == 2 then
  35.                 word = word:gsub('%-%P+', '') --remove the realm name but preserve any punctuation attached at the end
  36.             elseif #letterTable == 3 then
  37.                 word = word:gsub('%-%P+', '') --remove the realm name, but we're going to get stuck on the '
  38.                 word = word:gsub("%'%P+", '') --remove the rest of the realm name
  39.             end
  40.             coloredName = '|c'..RAID_CLASS_COLORS[class or class:gsub(' ', '')].colorStr..letterTable[1]..modChatColor --color the name
  41.             word = word:gsub(letterTable[1], coloredName) --replace the name with the colored name
  42.         end
  43.        
  44.         if (letterTable[1] and (letterTable[1]:lower() == 'you' or letterTable[1]:lower() == 'your')) then --color this
  45.             coloredName = '|c'..playerClassColorTable.colorStr..letterTable[1]..modChatColor --this is an addon-wide static formed at the beginning of the addon as it's frequently used
  46.             word = word:gsub(letterTable[1], coloredName)
  47.         end
  48.        
  49.         table.insert(coloredMessage, word)
  50.     end
  51.    
  52.     return(table.concat(coloredMessage, ' '))
  53. end

It works with non-ascii characters, works with off-realm players, works with people on realms with apostrophes, works under every scenario I can throw at it. It is fairly "hard-coded." I say that because player names can only be a name, a name-realm, or a name-re'alm with no numbers or punctuations in the name. This allowed me to perform the #letterTable == integer test.

Let me know what you think, or if you see a better way of doing this.

Last edited by Terenna : 01-08-19 at 06:57 PM. Reason: added both functions and commented the code more
  Reply With Quote