328 lines
11 KiB
Lua
328 lines
11 KiB
Lua
local ADDON_NAME = "HailMaryGuildTools"
|
|
local HMGT = _G[ADDON_NAME]
|
|
if not HMGT then return end
|
|
|
|
local L = HMGT.L or LibStub("AceLocale-3.0"):GetLocale(ADDON_NAME)
|
|
local AceGUI = LibStub("AceGUI-3.0", true)
|
|
local CLASS_ICON_TCOORDS = CLASS_ICON_TCOORDS or {}
|
|
|
|
local function NormalizeName(name)
|
|
if HMGT.NormalizePlayerName then
|
|
return HMGT:NormalizePlayerName(name)
|
|
end
|
|
return tostring(name or "")
|
|
end
|
|
|
|
local function GetRosterRows()
|
|
local rows = {}
|
|
local seen = {}
|
|
|
|
local function addUnit(unitId)
|
|
if not unitId or not UnitExists(unitId) then
|
|
return
|
|
end
|
|
local name = NormalizeName(UnitName(unitId))
|
|
if not name or name == "" or seen[name] then
|
|
return
|
|
end
|
|
seen[name] = true
|
|
rows[#rows + 1] = {
|
|
name = name,
|
|
class = select(2, UnitClass(unitId)),
|
|
isLeader = UnitIsGroupLeader and UnitIsGroupLeader(unitId) or false,
|
|
isAssistant = UnitIsGroupAssistant and UnitIsGroupAssistant(unitId) or false,
|
|
connected = UnitIsConnected and UnitIsConnected(unitId) ~= false or true,
|
|
isPlayer = UnitIsUnit and UnitIsUnit(unitId, "player") or unitId == "player",
|
|
}
|
|
end
|
|
|
|
if IsInRaid() then
|
|
for i = 1, GetNumGroupMembers() do
|
|
addUnit("raid" .. i)
|
|
end
|
|
elseif IsInGroup() then
|
|
addUnit("player")
|
|
for i = 1, GetNumSubgroupMembers() do
|
|
addUnit("party" .. i)
|
|
end
|
|
else
|
|
addUnit("player")
|
|
end
|
|
|
|
table.sort(rows, function(a, b)
|
|
if a.isLeader ~= b.isLeader then
|
|
return a.isLeader
|
|
end
|
|
if a.isPlayer ~= b.isPlayer then
|
|
return a.isPlayer
|
|
end
|
|
return tostring(a.name or "") < tostring(b.name or "")
|
|
end)
|
|
|
|
return rows
|
|
end
|
|
|
|
local function GetPlayerVersionText(name)
|
|
local normalized = NormalizeName(name)
|
|
if normalized == NormalizeName(UnitName("player")) then
|
|
return tostring(HMGT.ADDON_VERSION or "dev"), tonumber(HMGT.PROTOCOL_VERSION) or 0, true
|
|
end
|
|
|
|
local version = HMGT.peerVersions and HMGT.peerVersions[normalized] or nil
|
|
local protocol = HMGT.GetPeerProtocolVersion and HMGT:GetPeerProtocolVersion(normalized) or 0
|
|
if version and version ~= "" then
|
|
return tostring(version), tonumber(protocol) or 0, true
|
|
end
|
|
return nil, tonumber(protocol) or 0, false
|
|
end
|
|
|
|
local function ApplyClassIcon(texture, classTag)
|
|
if not texture then
|
|
return
|
|
end
|
|
|
|
local coords = classTag and CLASS_ICON_TCOORDS[classTag]
|
|
if coords then
|
|
texture:SetTexture("Interface\\GLUES\\CHARACTERCREATE\\UI-CHARACTERCREATE-CLASSES")
|
|
texture:SetTexCoord(coords[1], coords[2], coords[3], coords[4])
|
|
texture:Show()
|
|
else
|
|
texture:SetTexture(nil)
|
|
texture:Hide()
|
|
end
|
|
end
|
|
|
|
local function AcquireVersionRow(window, index)
|
|
window.versionRows = window.versionRows or {}
|
|
local row = window.versionRows[index]
|
|
if row then
|
|
return row
|
|
end
|
|
|
|
local parent = window.scrollChild
|
|
row = CreateFrame("Frame", nil, parent)
|
|
row:SetHeight(22)
|
|
|
|
row.background = row:CreateTexture(nil, "BACKGROUND")
|
|
row.background:SetAllPoints(row)
|
|
row.background:SetColorTexture(1, 1, 1, 0.03)
|
|
|
|
row.classIcon = row:CreateTexture(nil, "ARTWORK")
|
|
row.classIcon:SetSize(16, 16)
|
|
row.classIcon:SetPoint("LEFT", row, "LEFT", 4, 0)
|
|
|
|
row.nameText = row:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
|
|
row.nameText:SetPoint("LEFT", row.classIcon, "RIGHT", 6, 0)
|
|
row.nameText:SetJustifyH("LEFT")
|
|
|
|
row.versionText = row:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
|
|
row.versionText:SetPoint("LEFT", row, "LEFT", 250, 0)
|
|
row.versionText:SetWidth(150)
|
|
row.versionText:SetJustifyH("LEFT")
|
|
|
|
row.protocolText = row:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
|
|
row.protocolText:SetPoint("LEFT", row, "LEFT", 410, 0)
|
|
row.protocolText:SetWidth(100)
|
|
row.protocolText:SetJustifyH("LEFT")
|
|
|
|
window.versionRows[index] = row
|
|
return row
|
|
end
|
|
|
|
function HMGT:RefreshVersionNoticeWindow()
|
|
local window = self.versionNoticeWindow
|
|
if not window then
|
|
return
|
|
end
|
|
|
|
local roster = GetRosterRows()
|
|
local localName = NormalizeName(UnitName("player"))
|
|
|
|
for index, info in ipairs(roster) do
|
|
local row = AcquireVersionRow(window, index)
|
|
row:ClearAllPoints()
|
|
if index == 1 then
|
|
row:SetPoint("TOPLEFT", window.scrollChild, "TOPLEFT", 0, 0)
|
|
row:SetPoint("TOPRIGHT", window.scrollChild, "TOPRIGHT", 0, 0)
|
|
else
|
|
row:SetPoint("TOPLEFT", window.versionRows[index - 1], "BOTTOMLEFT", 0, -2)
|
|
row:SetPoint("TOPRIGHT", window.versionRows[index - 1], "BOTTOMRIGHT", 0, -2)
|
|
end
|
|
|
|
ApplyClassIcon(row.classIcon, info.class)
|
|
|
|
local nameLabel = tostring(info.name or UNKNOWN)
|
|
if info.isLeader then
|
|
nameLabel = string.format("%s %s", nameLabel, L["VERSION_WINDOW_LEADER_TAG"] or "(Leader)")
|
|
elseif info.isAssistant then
|
|
nameLabel = string.format("%s %s", nameLabel, L["VERSION_WINDOW_ASSISTANT_TAG"] or "(Assist)")
|
|
end
|
|
if info.isPlayer or info.name == localName then
|
|
nameLabel = string.format("%s %s", nameLabel, L["VERSION_WINDOW_SELF_TAG"] or "(You)")
|
|
end
|
|
|
|
row.nameText:SetText(nameLabel)
|
|
row.nameText:SetTextColor(1, 0.82, 0.1, 1)
|
|
|
|
local versionText, protocol, hasAddon = GetPlayerVersionText(info.name)
|
|
if hasAddon then
|
|
row.versionText:SetText(versionText or "?")
|
|
row.versionText:SetTextColor(0.9, 0.9, 0.9, 1)
|
|
row.protocolText:SetText(protocol > 0 and tostring(protocol) or "-")
|
|
row.protocolText:SetTextColor(0.75, 0.75, 0.75, 1)
|
|
else
|
|
row.versionText:SetText(L["VERSION_WINDOW_MISSING_ADDON"] or "Addon not installed")
|
|
row.versionText:SetTextColor(1, 0.25, 0.25, 1)
|
|
row.protocolText:SetText("-")
|
|
row.protocolText:SetTextColor(1, 0.25, 0.25, 1)
|
|
end
|
|
|
|
row:Show()
|
|
end
|
|
|
|
if window.versionRows then
|
|
for index = #roster + 1, #window.versionRows do
|
|
window.versionRows[index]:Hide()
|
|
end
|
|
end
|
|
|
|
local contentHeight = math.max(1, (#roster * 24))
|
|
window.scrollChild:SetHeight(contentHeight)
|
|
|
|
local known = 0
|
|
for _, info in ipairs(roster) do
|
|
local _, _, hasAddon = GetPlayerVersionText(info.name)
|
|
if hasAddon then
|
|
known = known + 1
|
|
end
|
|
end
|
|
|
|
window.messageText:SetText(L["VERSION_WINDOW_MESSAGE"] or "Hail Mary Guild Tools versions in your current group")
|
|
window.detailText:SetText(string.format(
|
|
L["VERSION_WINDOW_CURRENT"] or "Current version: %s | Protocol: %s",
|
|
tostring(HMGT.ADDON_VERSION or "dev"),
|
|
tostring(HMGT.PROTOCOL_VERSION or "?")
|
|
))
|
|
window:SetStatusText(string.format(
|
|
L["VERSION_WINDOW_STATUS"] or "Detected HMGT on %d/%d players",
|
|
tonumber(known) or 0,
|
|
tonumber(#roster) or 0
|
|
))
|
|
end
|
|
|
|
function HMGT:EnsureVersionNoticeWindow()
|
|
if self.versionNoticeWindow then
|
|
return self.versionNoticeWindow
|
|
end
|
|
|
|
self.versionNoticeWindowStatus = self.versionNoticeWindowStatus or {
|
|
width = 640,
|
|
height = 420,
|
|
}
|
|
|
|
local window = self:CreateAceWindow("versionNotice", {
|
|
title = L["VERSION_WINDOW_TITLE"] or "HMGT Version Check",
|
|
statusText = "",
|
|
statusTable = self.versionNoticeWindowStatus,
|
|
width = self.versionNoticeWindowStatus.width or 640,
|
|
height = self.versionNoticeWindowStatus.height or 420,
|
|
backgroundTexture = "Interface\\AddOns\\HailMaryGuildTools\\Media\\HailMaryLogo.png",
|
|
backgroundWidth = 220,
|
|
backgroundHeight = 120,
|
|
backgroundOffsetY = -8,
|
|
backgroundAlpha = 0.08,
|
|
strata = "FULLSCREEN_DIALOG",
|
|
})
|
|
if not window then
|
|
return nil
|
|
end
|
|
|
|
local content = window:GetContent()
|
|
|
|
local messageText = content:CreateFontString(nil, "OVERLAY", "GameFontHighlightLarge")
|
|
messageText:SetPoint("TOPLEFT", content, "TOPLEFT", 24, -22)
|
|
messageText:SetPoint("TOPRIGHT", content, "TOPRIGHT", -24, -22)
|
|
messageText:SetJustifyH("LEFT")
|
|
messageText:SetTextColor(1, 0.82, 0.1, 1)
|
|
window.messageText = messageText
|
|
|
|
local detailText = content:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
|
|
detailText:SetPoint("TOPLEFT", messageText, "BOTTOMLEFT", 0, -8)
|
|
detailText:SetPoint("TOPRIGHT", messageText, "BOTTOMRIGHT", 0, -8)
|
|
detailText:SetJustifyH("LEFT")
|
|
detailText:SetTextColor(0.9, 0.9, 0.9, 1)
|
|
window.detailText = detailText
|
|
|
|
local refreshButton = AceGUI and AceGUI:Create("Button") or nil
|
|
if refreshButton then
|
|
refreshButton:SetText(L["VERSION_WINDOW_REFRESH"] or "Refresh")
|
|
refreshButton:SetWidth(120)
|
|
refreshButton:SetCallback("OnClick", function()
|
|
HMGT:RequestSync("VersionWindow")
|
|
HMGT:RefreshVersionNoticeWindow()
|
|
end)
|
|
refreshButton.frame:SetParent(window.frame)
|
|
refreshButton.frame:ClearAllPoints()
|
|
refreshButton.frame:SetPoint("TOPRIGHT", content, "TOPRIGHT", -24, -68)
|
|
refreshButton.frame:Show()
|
|
window.refreshButton = refreshButton
|
|
end
|
|
|
|
local header = CreateFrame("Frame", nil, content)
|
|
header:SetPoint("TOPLEFT", detailText, "BOTTOMLEFT", 0, -14)
|
|
header:SetPoint("TOPRIGHT", content, "TOPRIGHT", -24, -96)
|
|
header:SetHeight(18)
|
|
window.header = header
|
|
|
|
local nameHeader = header:CreateFontString(nil, "OVERLAY", "GameFontNormal")
|
|
nameHeader:SetPoint("LEFT", header, "LEFT", 24, 0)
|
|
nameHeader:SetText(L["VERSION_WINDOW_COLUMN_PLAYER"] or "Player")
|
|
|
|
local versionHeader = header:CreateFontString(nil, "OVERLAY", "GameFontNormal")
|
|
versionHeader:SetPoint("LEFT", header, "LEFT", 250, 0)
|
|
versionHeader:SetText(L["VERSION_WINDOW_COLUMN_VERSION"] or "Version")
|
|
|
|
local protocolHeader = header:CreateFontString(nil, "OVERLAY", "GameFontNormal")
|
|
protocolHeader:SetPoint("LEFT", header, "LEFT", 410, 0)
|
|
protocolHeader:SetText(L["VERSION_WINDOW_COLUMN_PROTOCOL"] or "Protocol")
|
|
|
|
local scrollFrame = CreateFrame("ScrollFrame", nil, content, "UIPanelScrollFrameTemplate")
|
|
scrollFrame:SetPoint("TOPLEFT", header, "BOTTOMLEFT", 0, -6)
|
|
scrollFrame:SetPoint("BOTTOMRIGHT", content, "BOTTOMRIGHT", -28, 24)
|
|
window.scrollFrame = scrollFrame
|
|
|
|
local scrollChild = CreateFrame("Frame", nil, scrollFrame)
|
|
scrollChild:SetSize(1, 1)
|
|
scrollFrame:SetScrollChild(scrollChild)
|
|
window.scrollChild = scrollChild
|
|
|
|
self.versionNoticeWindow = window
|
|
return window
|
|
end
|
|
|
|
function HMGT:ShowVersionMismatchPopup(playerName, detail, sourceTag, opts)
|
|
opts = opts or {}
|
|
|
|
if playerName or detail or sourceTag then
|
|
self.latestVersionMismatch = {
|
|
playerName = playerName,
|
|
detail = detail,
|
|
sourceTag = sourceTag,
|
|
}
|
|
end
|
|
|
|
local window = self:EnsureVersionNoticeWindow()
|
|
if not window then
|
|
return
|
|
end
|
|
|
|
self:RefreshVersionNoticeWindow()
|
|
self:DevTrace("Version", "window_show", {
|
|
player = playerName,
|
|
source = sourceTag,
|
|
detail = detail,
|
|
})
|
|
window:Show()
|
|
window:Raise()
|
|
end
|