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.
410 lines
15 KiB
410 lines
15 KiB
local _, Cell = ...
|
|
local L = Cell.L
|
|
local F = Cell.funcs
|
|
|
|
local LibDeflate = LibStub:GetLibrary("LibDeflate")
|
|
local deflateConfig = {level = 9}
|
|
local Serializer = LibStub:GetLibrary("LibSerialize")
|
|
local Comm = LibStub:GetLibrary("AceComm-3.0")
|
|
|
|
local function Serialize(data)
|
|
local serialized = Serializer:Serialize(data) -- serialize
|
|
local compressed = LibDeflate:CompressDeflate(serialized, deflateConfig) -- compress
|
|
return LibDeflate:EncodeForWoWAddonChannel(compressed) -- encode
|
|
end
|
|
|
|
local function Deserialize(encoded)
|
|
local decoded = LibDeflate:DecodeForWoWAddonChannel(encoded) -- decode
|
|
local decompressed = LibDeflate:DecompressDeflate(decoded) -- decompress
|
|
if not decompressed then
|
|
F:Debug("Error decompressing: " .. errorMsg)
|
|
return
|
|
end
|
|
local success, data = Serializer:Deserialize(decompressed) -- deserialize
|
|
if not success then
|
|
F:Debug("Error deserializing: " .. data)
|
|
return
|
|
end
|
|
return data
|
|
end
|
|
|
|
-----------------------------------------
|
|
-- for WA
|
|
-----------------------------------------
|
|
function F:Notify(type, ...)
|
|
if WeakAuras then
|
|
WeakAuras.ScanEvents("CELL_NOTIFY", type, ...)
|
|
end
|
|
end
|
|
|
|
-----------------------------------------
|
|
-- shared
|
|
-----------------------------------------
|
|
local sendChannel
|
|
local function UpdateSendChannel()
|
|
if IsInGroup(LE_PARTY_CATEGORY_INSTANCE) then
|
|
sendChannel = "INSTANCE_CHAT"
|
|
elseif IsInRaid() then
|
|
sendChannel = "RAID"
|
|
else
|
|
sendChannel = "PARTY"
|
|
end
|
|
end
|
|
|
|
-----------------------------------------
|
|
-- Check Version
|
|
-----------------------------------------
|
|
local eventFrame = CreateFrame("Frame")
|
|
eventFrame:SetScript("OnEvent", function(self, event, ...)
|
|
self[event](self, ...)
|
|
end)
|
|
|
|
eventFrame:RegisterEvent("GROUP_ROSTER_UPDATE")
|
|
function eventFrame:GROUP_ROSTER_UPDATE()
|
|
if IsInGroup() then
|
|
eventFrame:UnregisterEvent("GROUP_ROSTER_UPDATE")
|
|
UpdateSendChannel()
|
|
Comm:SendCommMessage("CELL_VERSION", Cell.version, sendChannel, nil, "NORMAL")
|
|
end
|
|
end
|
|
|
|
eventFrame:RegisterEvent("PLAYER_LOGIN")
|
|
function eventFrame:PLAYER_LOGIN()
|
|
if IsInGuild() then
|
|
Comm:SendCommMessage("CELL_VERSION", Cell.version, "GUILD", nil, "NORMAL")
|
|
end
|
|
end
|
|
|
|
Comm:RegisterComm("CELL_VERSION", function(prefix, message, channel, sender)
|
|
if sender == UnitName("player") then return end
|
|
local version = tonumber(string.match(message, "%d+"))
|
|
local myVersion = tonumber(string.match(Cell.version, "%d+"))
|
|
if (not CellDB["lastVersionCheck"] or time()-CellDB["lastVersionCheck"]>=25200) and version and myVersion and myVersion < version then
|
|
CellDB["lastVersionCheck"] = time()
|
|
F:Print(L["New version found (%s). Please visit %s to get the latest version."]:format(message, "|cFF00CCFFhttps://www.curseforge.com/wow/addons/cell|r"))
|
|
end
|
|
end)
|
|
|
|
-----------------------------------------
|
|
-- Notify Marks
|
|
-----------------------------------------
|
|
Comm:RegisterComm("CELL_MARKS", function(prefix, message, channel, sender)
|
|
if sender == UnitName("player") then return end
|
|
local data = Deserialize(message)
|
|
if Cell.vars.hasPartyMarkPermission and CellDB["tools"]["marks"][1] and (strfind(CellDB["tools"]["marks"][3], "^target") or strfind(CellDB["tools"]["marks"][3], "^both")) and data then
|
|
sender = F:GetClassColorStr(select(2, UnitClass(sender)))..sender.."|r"
|
|
|
|
if data[1] then -- lock
|
|
F:Print(L["%s lock %s on %s."]:format(sender, F:GetMarkEscapeSequence(data[2]), data[3]))
|
|
else
|
|
F:Print(L["%s unlock %s from %s."]:format(sender, F:GetMarkEscapeSequence(data[2]), data[3]))
|
|
end
|
|
end
|
|
end)
|
|
|
|
function F:NotifyMarkLock(mark, name, class)
|
|
name = F:GetClassColorStr(class)..name.."|r"
|
|
F:Print(L["%s lock %s on %s."]:format(L["You"], F:GetMarkEscapeSequence(mark), name))
|
|
|
|
UpdateSendChannel()
|
|
Comm:SendCommMessage("CELL_MARKS", Serialize({true, mark, name}), sendChannel, nil, "ALERT")
|
|
end
|
|
|
|
function F:NotifyMarkUnlock(mark, name, class)
|
|
name = F:GetClassColorStr(class)..name.."|r"
|
|
F:Print(L["%s unlock %s from %s."]:format(L["You"], F:GetMarkEscapeSequence(mark), name))
|
|
|
|
UpdateSendChannel()
|
|
Comm:SendCommMessage("CELL_MARKS", Serialize({false, mark, name}), sendChannel, nil, "ALERT")
|
|
end
|
|
|
|
-----------------------------------------
|
|
-- Priority Check
|
|
-----------------------------------------
|
|
local myPriority
|
|
local highestPriority = 99
|
|
Cell.hasHighestPriority = false
|
|
|
|
local function UpdatePriority()
|
|
myPriority = 99
|
|
if UnitIsGroupLeader("player") then
|
|
myPriority = 0
|
|
else
|
|
if IsInRaid() then
|
|
for i = 1, GetNumGroupMembers() do
|
|
if UnitIsUnit("player", "raid"..i) then
|
|
myPriority = i
|
|
break
|
|
end
|
|
end
|
|
elseif IsInGroup() then -- party
|
|
local players = {}
|
|
local pName, pRealm = UnitFullName("player")
|
|
pRealm = pRealm or GetRealmName()
|
|
pName = pName.."-"..pRealm
|
|
tinsert(players, pName)
|
|
|
|
for i = 1, GetNumGroupMembers()-1 do
|
|
local name, realm = UnitFullName("party"..i)
|
|
tinsert(players, name.."-"..(realm or pRealm))
|
|
end
|
|
table.sort(players)
|
|
|
|
for i, p in pairs(players) do
|
|
if p == pName then
|
|
myPriority = i
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
local t_check, t_send, t_update
|
|
function F:CheckPriority()
|
|
UpdatePriority()
|
|
-- NOTE: needs time to calc myPriority
|
|
C_Timer.After(1, function()
|
|
UpdateSendChannel()
|
|
Comm:SendCommMessage("CELL_CPRIO", "chk", sendChannel, nil, "ALERT")
|
|
end)
|
|
-- if t_check then t_check:Cancel() end
|
|
-- t_check = C_Timer.NewTimer(2, function()
|
|
-- UpdateSendChannel()
|
|
-- Comm:SendCommMessage("CELL_CPRIO", "chk", sendChannel, nil, "BULK")
|
|
-- end)
|
|
end
|
|
|
|
Comm:RegisterComm("CELL_CPRIO", function(prefix, message, channel, sender)
|
|
if not myPriority then return end -- receive CELL_CPRIO just after GOURP_JOINED
|
|
highestPriority = 99
|
|
|
|
-- NOTE: wait for check requests
|
|
if t_send then t_send:Cancel() end
|
|
t_send = C_Timer.NewTimer(2, function()
|
|
UpdateSendChannel()
|
|
Comm:SendCommMessage("CELL_PRIO", tostring(myPriority), sendChannel, nil, "ALERT")
|
|
end)
|
|
end)
|
|
|
|
Comm:RegisterComm("CELL_PRIO", function(prefix, message, channel, sender)
|
|
if not myPriority then return end -- receive CELL_PRIO just after GOURP_JOINED
|
|
|
|
local p = tonumber(message)
|
|
if p then
|
|
highestPriority = highestPriority < p and highestPriority or p
|
|
|
|
if t_update then t_update:Cancel() end
|
|
t_update = C_Timer.NewTimer(2, function()
|
|
Cell.hasHighestPriority = myPriority <= highestPriority
|
|
Cell:Fire("UpdatePriority", Cell.hasHighestPriority)
|
|
F:Debug("|cff00ff00UpdatePriority:|r", Cell.hasHighestPriority)
|
|
end)
|
|
end
|
|
end)
|
|
|
|
-----------------------------------------
|
|
-- cross realm send
|
|
-----------------------------------------
|
|
local function CrossRealmSendCommMessage(prefix, message, playerName, priority, callbackFn)
|
|
-- NOTE: unit needs to be in your group, or it will always return true
|
|
if UnitIsSameServer(playerName) then
|
|
Comm:SendCommMessage(prefix, message, "WHISPER", playerName, priority, callbackFn)
|
|
else
|
|
if UnitInParty(playerName) then
|
|
Comm:SendCommMessage(prefix, playerName..":"..message, "PARTY", nil, priority, callbackFn)
|
|
elseif UnitInRaid(playerName) then
|
|
Comm:SendCommMessage(prefix, playerName..":"..message, "RAID", nil, priority, callbackFn)
|
|
end
|
|
end
|
|
end
|
|
|
|
-----------------------------------------
|
|
-- Send / Receive Raid Debuffs and Layouts
|
|
-----------------------------------------
|
|
local function filterFunc(self, event, msg, player, arg1, arg2, arg3, flag, channelId, ...)
|
|
local newMsg = ""
|
|
|
|
local type = msg:match("%[Cell:(.+): .+]")
|
|
if type == "Debuffs" then
|
|
local bossName, instanceName, playerName = msg:match("%[Cell:Debuffs: (.+) %((.+)%) %- ([^%s]+%-[^%s]+)%]")
|
|
if bossName and instanceName and playerName then
|
|
newMsg = "|Hgarrmission:cell-debuffs|h|cFFFF0066["..L[type]..": "..bossName.." ("..instanceName..") - "..playerName.."]|h|r"
|
|
else
|
|
instanceName, playerName = msg:match("%[Cell:Debuffs: (.+) %- ([^%s]+%-[^%s]+)%]")
|
|
if instanceName and playerName then
|
|
newMsg = "|Hgarrmission:cell-debuffs|h|cFFFF0066["..L[type]..": "..instanceName.." - "..playerName.."]|h|r"
|
|
end
|
|
end
|
|
elseif type == "Layout" then
|
|
local layoutName, playerName = msg:match("%[Cell:Layout: (.+) %- ([^%s]+%-[^%s]+)%]")
|
|
if layoutName and playerName then
|
|
if layoutName == "default" then
|
|
-- NOTE: convert "default"
|
|
layoutName = _G.DEFAULT
|
|
end
|
|
newMsg = "|Hgarrmission:cell-layout|h|cFFFF0066["..L[type]..": "..layoutName.." - "..playerName.."]|h|r"
|
|
end
|
|
end
|
|
|
|
if newMsg ~= "" then
|
|
return false, newMsg, player, arg1, arg2, arg3, flag, channelId, ...
|
|
end
|
|
end
|
|
|
|
ChatFrame_AddMessageEventFilter("CHAT_MSG_CHANNEL", filterFunc)
|
|
ChatFrame_AddMessageEventFilter("CHAT_MSG_YELL", filterFunc)
|
|
ChatFrame_AddMessageEventFilter("CHAT_MSG_GUILD", filterFunc)
|
|
ChatFrame_AddMessageEventFilter("CHAT_MSG_OFFICER", filterFunc)
|
|
ChatFrame_AddMessageEventFilter("CHAT_MSG_PARTY", filterFunc)
|
|
ChatFrame_AddMessageEventFilter("CHAT_MSG_PARTY_LEADER", filterFunc)
|
|
ChatFrame_AddMessageEventFilter("CHAT_MSG_RAID", filterFunc)
|
|
ChatFrame_AddMessageEventFilter("CHAT_MSG_RAID_LEADER", filterFunc)
|
|
ChatFrame_AddMessageEventFilter("CHAT_MSG_SAY", filterFunc)
|
|
ChatFrame_AddMessageEventFilter("CHAT_MSG_WHISPER", filterFunc)
|
|
ChatFrame_AddMessageEventFilter("CHAT_MSG_WHISPER_INFORM", filterFunc)
|
|
ChatFrame_AddMessageEventFilter("CHAT_MSG_BN_WHISPER", filterFunc)
|
|
ChatFrame_AddMessageEventFilter("CHAT_MSG_BN_WHISPER_INFORM", filterFunc)
|
|
ChatFrame_AddMessageEventFilter("CHAT_MSG_INSTANCE_CHAT", filterFunc)
|
|
ChatFrame_AddMessageEventFilter("CHAT_MSG_INSTANCE_CHAT_LEADER", filterFunc)
|
|
|
|
local isRequesting
|
|
|
|
-- NOTE: received
|
|
Comm:RegisterComm("CELL_SEND", function(prefix, message, channel, sender)
|
|
if not isRequesting then return end
|
|
if channel ~= "WHISPER" then
|
|
local target
|
|
target, message = strsplit(":", message, 2)
|
|
if target ~= Cell.vars.playerNameFull then
|
|
return
|
|
end
|
|
end
|
|
|
|
local receivedData = Deserialize(message)
|
|
|
|
if Cell.frames.receivingFrame then
|
|
if receivedData then
|
|
Cell.frames.receivingFrame:ShowImport(true, receivedData, function()
|
|
isRequesting = false
|
|
end)
|
|
else
|
|
Cell.frames.receivingFrame:ShowImport(false, nil, function()
|
|
isRequesting = false
|
|
end)
|
|
end
|
|
end
|
|
end)
|
|
|
|
-- NOTE: progress received
|
|
Comm:RegisterComm("CELL_SEND_PROG", function(prefix, message, channel, sender)
|
|
if not isRequesting then return end
|
|
if channel ~= "WHISPER" then
|
|
local target
|
|
target, message = strsplit(":", message, 2)
|
|
if target ~= Cell.vars.playerNameFull then
|
|
return
|
|
end
|
|
end
|
|
|
|
local done, total = strsplit("|", message)
|
|
done, total = tonumber(done), tonumber(total)
|
|
|
|
if Cell.frames.receivingFrame then
|
|
Cell.frames.receivingFrame:ShowProgress(done, total)
|
|
end
|
|
end)
|
|
|
|
-- NOTE: request received
|
|
Comm:RegisterComm("CELL_REQ", function(prefix, message, channel, requester)
|
|
if channel ~= "WHISPER" then
|
|
local target
|
|
target, message = strsplit(":", message, 2)
|
|
if target ~= Cell.vars.playerNameFull then
|
|
return
|
|
end
|
|
end
|
|
|
|
-- check request
|
|
local type, name1, name2 = strsplit(":", message)
|
|
local requestData
|
|
|
|
-- print(type, name1, name2)
|
|
if type == "Debuffs" then
|
|
local instanceId, bossId = F:GetInstanceAndBossId(name1, name2)
|
|
if not instanceId then return end -- invalid instanceName
|
|
|
|
requestData = {
|
|
["type"] = "Debuffs",
|
|
["instanceId"] = instanceId,
|
|
["bossId"] = bossId,
|
|
["version"] = Cell.versionNum
|
|
}
|
|
|
|
-- check db
|
|
if not bossId then -- all bosses
|
|
if CellDB["raidDebuffs"][instanceId] then
|
|
requestData["data"] = CellDB["raidDebuffs"][instanceId]
|
|
end
|
|
else
|
|
if CellDB["raidDebuffs"][instanceId] and CellDB["raidDebuffs"][instanceId][bossId] then
|
|
requestData["data"] = CellDB["raidDebuffs"][instanceId][bossId]
|
|
end
|
|
end
|
|
elseif type == "Layout" then
|
|
if name1 == _G.DEFAULT then
|
|
-- NOTE: convert "DEFAULT"
|
|
name1 = "default"
|
|
end
|
|
if name1 and CellDB["layouts"][name1] then
|
|
requestData = {
|
|
["type"] = "Layout",
|
|
["name"] = name1,
|
|
["version"] = Cell.versionNum,
|
|
["data"] = CellDB["layouts"][name1]
|
|
}
|
|
end
|
|
end
|
|
|
|
-- texplore(requestData)
|
|
|
|
if not requestData then return end
|
|
CrossRealmSendCommMessage("CELL_SEND", Serialize(requestData), requester, "BULK", function(arg, done, total)
|
|
-- send progress
|
|
CrossRealmSendCommMessage("CELL_SEND_PROG", done.."|"..total, requester, "ALERT")
|
|
end)
|
|
end)
|
|
|
|
local function ShowReceivingFrame(type, playerName, name1, name2)
|
|
if not Cell.frames.receivingFrame then
|
|
Cell.frames.receivingFrame = Cell:CreateReceivingFrame(Cell.frames.mainFrame)
|
|
Cell.frames.receivingFrame:SetOnCancel(function(b)
|
|
isRequesting = false
|
|
end)
|
|
end
|
|
|
|
Cell.frames.receivingFrame:SetOnRequest(function(b)
|
|
isRequesting = true
|
|
--! send request
|
|
CrossRealmSendCommMessage("CELL_REQ", type..":"..name1..":"..(name2 or ""), playerName, "ALERT")
|
|
end)
|
|
|
|
Cell.frames.receivingFrame:ShowFrame(type, playerName, name1, name2)
|
|
end
|
|
|
|
hooksecurefunc("SetItemRef", function(link, text)
|
|
if isRequesting then return end
|
|
if link == "garrmission:cell-debuffs" then
|
|
local bossName, instanceName, playerName = text:match("|Hgarrmission:cell%-debuffs|h|cFFFF0066%[.+: (.+) %((.+)%) %- ([^%s]+%-[^%s]+)%]|h|r")
|
|
if bossName and instanceName and playerName then
|
|
ShowReceivingFrame("Debuffs", playerName, instanceName, bossName)
|
|
else
|
|
instanceName, playerName = text:match("|Hgarrmission:cell%-debuffs|h|cFFFF0066%[.+: (.+) %- ([^%s]+%-[^%s]+)%]|h|r")
|
|
ShowReceivingFrame("Debuffs", playerName, instanceName)
|
|
end
|
|
elseif link == "garrmission:cell-layout" then
|
|
local layoutName, playerName = text:match("|Hgarrmission:cell%-layout|h|cFFFF0066%[.+: (.+) %- ([^%s]+%-[^%s]+)%]|h|r")
|
|
ShowReceivingFrame("Layout", playerName, layoutName)
|
|
end
|
|
end)
|