libunitscan: cache levels only, classes come from C_PlayerCache

This commit is contained in:
Brues
2026-11-03 01:17:04 -06:00
parent df7c13651b
commit ee9bd9e31a
4 changed files with 55 additions and 88 deletions
+45 -66
View File
@@ -2,20 +2,17 @@
setfenv(1, pfUI:GetEnvironment())
--[[ libunitscan ]]--
-- A pfUI library that remembers the class, level and guild of every player it
-- sees: in the friends, guild, raid and party rosters, in /who results, and as
-- target, mouseover or nameplate. The data is persisted within pfUI_playerDB,
-- for the places that only have a player's name, such as chat links and
-- offline friends. Anything with a unit reads the unit itself instead.
-- A pfUI library that remembers the level of every player it sees: in the
-- friends, guild, raid and party rosters, in /who results, and as target,
-- mouseover or nameplate. The levels are persisted within pfUI_playerDB, for
-- the places that only have a player's name, such as chat links and offline
-- friends. Anything with a unit reads the unit itself instead. A player's
-- class comes from C_PlayerCache.GetPlayerInfoByName, not from here.
--
-- External functions:
-- GetUnitInfo(name)
-- Returns information of the given player name. Returns nil if the player
-- was never seen.
--
-- class[String] - The class of the player
-- level[Number] - The level of the player
-- guild[String] - The guild name of the player
-- GetPlayerLevel(name)
-- Returns the last seen level of the given player name, or nil if it was
-- never seen.
--
-- return instantly when another libunitscan is already active
@@ -23,33 +20,33 @@ if pfUI.api.libunitscan then return end
local players = {}
-- Feed (guid, name, classToken) into ClassicAPI's persistent name
-- cache when the unit's GUID is resolvable. Roster-style packets
-- (party / raid / inspect on glance) carry class inline, so the
-- engine often doesn't issue a separate name query and the DLL's
-- NameCache hook never fires for them — this is where we close that gap.
local function RememberByUnit(unit, name, class)
if not (name and class) then return end
-- Feed a unit into ClassicAPI's persistent name cache. Roster-style packets
-- (party / raid / inspect on glance) carry class inline, so the engine often
-- doesn't issue a separate name query and the DLL's NameCache hook never
-- fires for them — this is where we close that gap.
local function RememberByUnit(unit)
local guid = UnitGUID(unit)
if not guid then return end
C_PlayerCache.RememberPlayer(guid, name, class, UnitRace(unit), UnitSex(unit))
local _, race = UnitRace(unit)
C_PlayerCache.RememberPlayer(guid, UnitName(unit), UnitClassBase(unit), race, UnitSex(unit) - 2)
end
function GetUnitInfo(name)
local ret = players[name]
if ret then
return ret.class, ret.level, ret.guild
function GetPlayerLevel(name)
local entry = players[name]
return entry and entry.level
end
-- UnitLevel returns -1 for unknown levels, don't overwrite known values
local function AddLevel(name, level)
if not name or not level or level <= 0 then return end
local entry = players[name]
if entry then
entry.level = level
else
players[name] = { level = level }
end
end
local function AddData(name, class, level, guild)
if not name then return end
players[name] = players[name] or {}
players[name].class = class or players[name].class
players[name].level = level or players[name].level
players[name].guild = guild or players[name].guild
end
local libunitscan = CreateFrame("Frame", "pfUnitScan", UIParent)
libunitscan:RegisterEvent("PLAYER_ENTERING_WORLD")
libunitscan:RegisterEvent("FRIENDLIST_UPDATE")
@@ -68,58 +65,45 @@ libunitscan:SetScript("OnEvent", function()
players = pfUI_playerDB
-- update own character details
local name = UnitName("player")
local class = UnitClassBase("player")
local level = UnitLevel("player")
local guild = GetGuildInfo("player")
AddData(name, class, level, guild)
RememberByUnit("player", name, class)
AddLevel(UnitName("player"), UnitLevel("player"))
RememberByUnit("player")
elseif event == "FRIENDLIST_UPDATE" then
for i = 1, GetNumFriends() do
local info = C_FriendList.GetFriendInfoByIndex(i)
if info then
local level = info.level > 0 and info.level or nil
AddData(info.name, info.classFilename, level)
AddLevel(info.name, info.level)
end
end
elseif event == "GUILD_ROSTER_UPDATE" then
local guild = GetGuildInfo("player")
local name, class, level, _
local name, level, _
for i = 1, GetNumGuildMembers() do
name, _, _, level, class = GetGuildRosterInfo(i)
class = L["class"][class] or nil
AddData(name, class, level, guild)
name, _, _, level = GetGuildRosterInfo(i)
AddLevel(name, level)
end
elseif event == "RAID_ROSTER_UPDATE" then
local name, class, level, unit, _
local name, level, _
for i = 1, GetNumRaidMembers() do
unit = "raid" .. i
name, _, _, level, class = GetRaidRosterInfo(i)
class = L["class"][class] or nil
AddData(name, class, level)
RememberByUnit(unit, name, class)
name, _, _, level = GetRaidRosterInfo(i)
AddLevel(name, level)
RememberByUnit("raid" .. i)
end
elseif event == "PARTY_MEMBERS_CHANGED" then
local name, class, level, unit, guild
local unit
for i = 1, GetNumPartyMembers() do
unit = "party" .. i
class = UnitClassBase(unit)
name = UnitName(unit)
level = UnitLevel(unit)
guild = GetGuildInfo(unit)
AddData(name, class, level, guild)
RememberByUnit(unit, name, class)
AddLevel(UnitName(unit), UnitLevel(unit))
RememberByUnit(unit)
end
elseif event == "WHO_LIST_UPDATE" or event == "CHAT_MSG_SYSTEM" then
for i = 1, C_FriendList.GetNumWhoResults() do
local info = C_FriendList.GetWhoInfo(i)
if info then
AddData(info.fullName, info.filename, info.level, info.fullGuildName)
AddLevel(info.fullName, info.level)
end
end
@@ -128,13 +112,8 @@ libunitscan:SetScript("OnEvent", function()
or event == "NAME_PLATE_UNIT_ADDED" and arg1
or "mouseover"
if UnitIsPlayer(scan) then
local name = UnitName(scan)
local class = UnitClassBase(scan)
-- UnitLevel returns -1 for unknown levels, don't overwrite known values
local level = UnitLevel(scan)
level = level > 0 and level or nil
AddData(name, class, level, GetGuildInfo(scan))
RememberByUnit(scan, name, class)
AddLevel(UnitName(scan), UnitLevel(scan))
RememberByUnit(scan)
end
end
end)