WOW_Collection_System/SM_Events.lua

730 lines
28 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- SM_Events.lua
-- 斜杠命令
SLASH_SM_COLLECTIONS1 = "/smcollections"
SLASH_SM_COLLECTIONS2 = "/sm收藏"
SlashCmdList["SM_COLLECTIONS"] = function()
if SM_Collections.MainFrame:IsVisible() then
SM_Collections.MainFrame:Hide()
else
SM_Collections.MainFrame:Show()
if not SM_Collections.CurrentTab then
SM_Collections:ShowTab(1)
end
end
end
-- 处理坐骑数据
function SM_Collections:HandleMountsData(msg)
local data = self:MessageSplit(msg, "|")
for i = 1, math.min(20, #data) do
end
local mounts = {}
for i = 1, #data, 4 do
if data[i] and data[i + 1] and data[i + 2] and data[i + 3] then
local mountID = tonumber(data[i])
-- 获取正确的显示ID
local displayID = nil
if SM_Collections.SpellToDisplayIDMap and SM_Collections.SpellToDisplayIDMap[mountID] then
displayID = SM_Collections.SpellToDisplayIDMap[mountID].effectMiscValue
end
-- 尝试从游戏中获取技能信息,添加错误处理
local spellName, spellRank, spellIcon
if mountID and type(mountID) == "number" and mountID > 0 then
-- 使用pcall安全地调用GetSpellInfo防止错误导致整个函数崩溃
local success, result = pcall(function()
return GetSpellInfo(mountID)
end)
if success and result then
spellName = result
_, _, spellIcon = GetSpellInfo(mountID) -- 再次调用获取图标
else
spellName = nil
spellIcon = nil
end
else
spellName = nil
spellIcon = nil
end
table.insert(mounts, {
id = mountID,
name = data[i + 1] or spellName or ("坐骑 #" .. mountID), -- 如果服务端名称为空尝试使用GetSpellInfo获取或使用默认值
description = data[i + 2],
obtained = data[i + 3] == "1",
displayID = displayID, -- 存储正确的显示ID
spellName = spellName, -- 存储从GetSpellInfo获取的名称作为备用
icon = spellIcon -- 存储图标
})
end
end
if self.pendingCallbacks and self.pendingCallbacks.mounts then
-- 创建假的response对象标记成功获取了数据
local response = {
success = true,
data = mounts
}
self.pendingCallbacks.mounts(response)
self.pendingCallbacks.mounts = nil
else
end
end
-- 处理属性数据
function SM_Collections:HandleAttributesData(msg)
print("[收藏系统] 处理属性数据:", msg)
local data = self:MessageSplit(msg, "|")
local attributes = {}
for i = 1, #data, 3 do
if data[i] and data[i + 1] and data[i + 2] then
table.insert(attributes, {
Name = data[i],
value = tonumber(data[i + 1]),
isPositive = data[i + 2] == "1"
})
end
end
if self.pendingCallbacks and self.pendingCallbacks.attributes then
local response = {
success = true,
data = attributes
}
self.pendingCallbacks.attributes(response)
self.pendingCallbacks.attributes = nil
else
end
end
-- 处理物品属性数据的函数
function SM_Collections:HandleItemAttributesData(msg)
-- 按换行符分割每一行属性数据
local lines = {}
for line in msg:gmatch("[^\r\n]+") do
table.insert(lines, line)
end
local allAttributes = {}
-- 处理每一行属性数据
for _, line in ipairs(lines) do
-- 使用自定义的MessageSplit函数将每行按"|"分隔符拆分
local data = self:MessageSplit(line, "|")
-- 每3个元素为一组进行循环处理属性名、属性值、属性类型
for i = 1, #data, 3 do
if data[i] and data[i + 1] and data[i + 2] then
-- 创建属性对象
local attribute = {
Name = data[i], -- 属性名称
value = tonumber(data[i + 1]), -- 属性数值
valueType = data[i + 2], -- 属性类型(百分比/固定数值)
isPositive = tonumber(data[i + 1]) >= 0 -- 根据数值正负判断是否为正面属性
}
-- 输出每个属性的值
print("Name= " .. attribute.Name .. ", value= " .. attribute.value .. ", valueType= " .. attribute.valueType)
-- 添加到属性数组
table.insert(allAttributes, attribute)
end
end
end
-- 检查是否存在待处理的回调函数
if self.pendingCallbacks and self.pendingCallbacks.item_attributes then
local response = {
success = true,
data = allAttributes
}
self.pendingCallbacks.item_attributes(response)
self.pendingCallbacks.item_attributes = nil
end
end
-- 处理小伙伴数据
function SM_Collections:HandleCompanionsData(msg)
local data = self:MessageSplit(msg, "|")
local companions = {}
for i = 1, #data, 4 do
if data[i] and data[i + 1] and data[i + 2] and data[i + 3] then
local companionID = tonumber(data[i])
-- 获取正确的显示ID
local displayID = nil
if SM_Collections.Companions and SM_Collections.Companions[companionID] then
displayID = SM_Collections.Companions[companionID].effectMiscValue
end
-- 尝试从游戏中获取技能信息,添加错误处理
local spellName, spellRank, spellIcon
if companionID and type(companionID) == "number" and companionID > 0 then
-- 使用pcall安全地调用GetSpellInfo防止错误导致整个函数崩溃
local success, result = pcall(function()
return GetSpellInfo(companionID)
end)
if success and result then
spellName = result
_, _, spellIcon = GetSpellInfo(companionID) -- 再次调用获取图标
else
spellName = nil
spellIcon = nil
end
else
--
spellName = nil
spellIcon = nil
end
table.insert(companions, {
id = companionID,
name = data[i + 1] or spellName or ("小伙伴 #" .. companionID), -- 如果服务端名称为空尝试使用GetSpellInfo获取或使用默认值
description = data[i + 2],
obtained = data[i + 3] == "1",
displayID = displayID, -- 存储正确的显示ID
spellName = spellName, -- 存储从GetSpellInfo获取的名称作为备用
icon = spellIcon -- 存储图标
})
end
end
if self.pendingCallbacks and self.pendingCallbacks.companions then
-- 创建假的response对象标记成功获取了数据
local response = {
success = true,
data = companions
}
self.pendingCallbacks.companions(response)
self.pendingCallbacks.companions = nil
else
--
end
end
-- 处理卡牌数据
function SM_Collections:HandleCardsData(msg)
local data = self:MessageSplit(msg, "|")
local cards = {}
-- 检查数据格式,尝试修复不规则的数据
if #data >= 4 then
local i = 1
while i <= #data do
local id, name, description, obtained
-- 尝试解析ID必须是数字
id = tonumber(data[i])
if id then
-- 获取名称
name = data[i + 1] or ""
-- 获取描述,如果描述不存在,尝试使用下一个字段
description = data[i + 2] or ""
-- 获取获得状态,尝试查找"1"或"0"
local obtainedStr = data[i + 3] or "0"
obtained = (obtainedStr == "1")
-- 创建卡牌对象
table.insert(cards, {
id = id,
name = name,
description = description,
obtained = obtained
})
-- 输出调试信息
end
-- 移动到下一组数据
i = i + 4
end
end
if self.pendingCallbacks and self.pendingCallbacks.cards then
local response = {
success = true,
data = cards
}
self.pendingCallbacks.cards(response)
self.pendingCallbacks.cards = nil
else
--
end
end
-- 处理物品数据
function SM_Collections:HandleItemsData(msg)
-- 缓存机制:如果不存在,初始化缓存
if not self.itemDataCache then
self.itemDataCache = ""
end
-- 将新收到的数据追加到缓存
self.itemDataCache = self.itemDataCache .. msg
-- 我们暂时不处理数据,而是等待更多批次数据到达
-- 只有当收到回调请求或者达到一定大小时才处理
if not self.pendingCallbacks or not self.pendingCallbacks.items then
return
end
-- 确保所有服务器数据都已接收等待2秒再处理
if not self.itemDataProcessTimer then
self.itemDataProcessTimer = true
local processFrame = CreateFrame("Frame")
processFrame:SetScript("OnUpdate", function(self, elapsed)
self.elapsed = (self.elapsed or 0) + elapsed
if self.elapsed >= 2 then
self:SetScript("OnUpdate", nil)
self:Hide()
-- 处理缓存中的所有数据
SM_Collections:ProcessItemsData()
end
end)
processFrame:Show()
return
end
end
-- 新增:处理缓存中的所有物品数据
function SM_Collections:ProcessItemsData()
local data = self:MessageSplit(self.itemDataCache, "|")
local items = {}
-- 确认每组数据的字段数 - 每个物品固定为5个字段
local fieldsPerItem = 5 -- ID、名称、描述、是否获得、类型
-- 循环处理数据严格按照5个字段一组来解析
local validItemCount = 0
local slotItems = {} -- 按物品类型统计数量
for i = 1, #data, fieldsPerItem do
-- 确保有完整的5个字段
if i + fieldsPerItem - 1 <= #data then
local itemID = tonumber(data[i])
local itemName = data[i + 1]
local itemDesc = data[i + 2]
local obtained = data[i + 3] == "1"
local itemType = data[i + 4]
if itemID and itemID > 0 then
-- 统计不同类型物品的数量
if itemType and itemType ~= "" then
slotItems[itemType] = (slotItems[itemType] or 0) + 1
end
table.insert(items, {
id = itemID,
name = itemName or "",
description = itemDesc or "",
obtained = obtained,
itemType = itemType or ""
})
validItemCount = validItemCount + 1
end
end
end
if self.pendingCallbacks and self.pendingCallbacks.items then
local response = {
success = true,
data = items
}
self.pendingCallbacks.items(response)
self.pendingCallbacks.items = nil
-- 重置缓存和定时器
self.itemDataCache = ""
self.itemDataProcessTimer = nil
end
end
-- 处理收藏状态更新
function SM_Collections:HandleCollectionUpdate(msg)
local data = self:MessageSplit(msg, "|")
if #data >= 3 then
local itemType = data[1]
local itemID = tonumber(data[2])
local isObtained = (data[3] == "1")
-- 确保数据结构存在
if not SM_CollectionsDB then
SM_CollectionsDB = {
mountCache = { mounts = {} },
companionCache = { companions = {} },
cardCache = { cards = {} },
itemCache = { items = {} }
}
end
-- 同步更新SM_CollectionsDB数据确保立即生效
if itemType == "mount" and SM_CollectionsDB.mountCache then
local found = false
for i, mount in ipairs(SM_CollectionsDB.mountCache.mounts or {}) do
if mount.id == itemID then
mount.obtained = isObtained
found = true
break
end
end
if not found and isObtained then
table.insert(SM_CollectionsDB.mountCache.mounts, {id = itemID, obtained = true})
end
elseif itemType == "companion" and SM_CollectionsDB.companionCache then
local found = false
for i, companion in ipairs(SM_CollectionsDB.companionCache.companions or {}) do
if companion.id == itemID then
companion.obtained = isObtained
found = true
break
end
end
if not found and isObtained then
table.insert(SM_CollectionsDB.companionCache.companions, {id = itemID, obtained = true})
end
elseif itemType == "card" and SM_CollectionsDB.cardCache then
local found = false
for i, card in ipairs(SM_CollectionsDB.cardCache.cards or {}) do
if card.id == itemID then
card.obtained = isObtained
found = true
break
end
end
if not found and isObtained then
table.insert(SM_CollectionsDB.cardCache.cards, {id = itemID, obtained = true})
end
elseif itemType == "item" and SM_CollectionsDB.itemCache then
local found = false
for i, item in ipairs(SM_CollectionsDB.itemCache.items or {}) do
if tonumber(item.id) == itemID then
item.obtained = isObtained
found = true
break
end
end
if not found and isObtained then
table.insert(SM_CollectionsDB.itemCache.items, {id = itemID, obtained = true})
end
-- 立即执行物品排序,不等待延迟
self:ForceItemReordering(itemID)
end
if itemID and itemType then
-- 更新本地数据
if itemType == "mount" then
self.DataManager:UpdateMountStatus(itemID, isObtained)
-- 如果是新获得的坐骑记录到NewItems表中
if isObtained then
self.NewItems.mount[itemID] = true
end
elseif itemType == "companion" then
self.DataManager:UpdateCompanionStatus(itemID, isObtained)
-- 如果是新获得的小伙伴记录到NewItems表中
if isObtained then
self.NewItems.companion[itemID] = true
end
elseif itemType == "card" then
self.DataManager:UpdateCardStatus(itemID, isObtained)
-- 如果是新获得的卡牌记录到NewItems表中
if isObtained then
self.NewItems.card[itemID] = true
end
elseif itemType == "item" then
self.DataManager:UpdateItemStatus(itemID, isObtained)
-- 如果是新获得的物品记录到NewItems表中
if isObtained then
self.NewItems.item[itemID] = true
end
end
-- 检查当前是否显示了对应类型的面板
local isCurrentPanel = false
if self.MainFrame then
-- 如果tabID为nil尝试从CurrentPanel推断当前面板类型
local inferredTabID = nil
if not self.MainFrame.tabID and self.CurrentPanel then
-- 检查当前面板中的按钮数据类型
if self.CurrentPanel.scrollChild and self.CurrentPanel.scrollChild.buttons and #self.CurrentPanel.scrollChild.buttons > 0 then
local firstButton = self.CurrentPanel.scrollChild.buttons[1]
if firstButton and firstButton.itemType then
if firstButton.itemType == "mount" then
inferredTabID = 1
elseif firstButton.itemType == "companion" then
inferredTabID = 2
elseif firstButton.itemType == "card" then
inferredTabID = 3
elseif firstButton.itemType == "item" then
inferredTabID = 4
end
end
end
end
local effectiveTabID = self.MainFrame.tabID or inferredTabID
if effectiveTabID then
if (itemType == "mount" and effectiveTabID == 1) or
(itemType == "companion" and effectiveTabID == 2) or
(itemType == "card" and effectiveTabID == 3) or
(itemType == "item" and effectiveTabID == 4) then
isCurrentPanel = true
end
end
end
-- 无论当前面板是什么都尝试刷新UI
-- 如果不是当前面板RefreshCollectionStatus函数内部会自己处理
self:RefreshCollectionStatus(itemType, itemID, isObtained)
-- 如果是卡牌且当前显示的是卡牌面板,强制重新加载
if itemType == "card" and isCurrentPanel then
-- 使用 3.3.5 支持的延迟执行方法
local cardReloadFrame = CreateFrame("Frame")
cardReloadFrame:SetScript("OnUpdate", function(self, elapsed)
self.elapsed = (self.elapsed or 0) + elapsed
if self.elapsed >= 0.1 then
self:SetScript("OnUpdate", nil)
self:Hide()
SM_Collections:ShowCards()
end
end)
cardReloadFrame:Show()
end
-- 如果是卡牌且获得了新卡牌,强制重新加载卡牌面板
if itemType == "card" and isObtained and not isCurrentPanel then
-- 更新本地数据,但不切换面板
local cardDataReloadFrame = CreateFrame("Frame")
cardDataReloadFrame:SetScript("OnUpdate", function(self, elapsed)
self.elapsed = (self.elapsed or 0) + elapsed
if self.elapsed >= 0.1 then
self:SetScript("OnUpdate", nil)
self:Hide()
-- 重新获取卡牌数据,但不显示
SM_Collections.DataManager:GetCards(function(cards)
end)
end
end)
cardDataReloadFrame:Show()
end
-- 如果是小伙伴且获得了新的小伙伴,强制重新加载小伙伴面板
if itemType == "companion" and isObtained then
-- 使用 3.3.5 支持的延迟执行方法
local companionReloadFrame = CreateFrame("Frame")
companionReloadFrame:SetScript("OnUpdate", function(self, elapsed)
self.elapsed = (self.elapsed or 0) + elapsed
if self.elapsed >= 0.1 then
self:SetScript("OnUpdate", nil)
self:Hide()
if SM_Collections.MainFrame and SM_Collections.MainFrame.tabID == 2 then
SM_Collections:ShowCompanions()
end
end
end)
companionReloadFrame:Show()
end
-- 如果是物品且获得了新物品,强制重新加载物品面板
if itemType == "item" and isObtained then
-- 使用 3.3.5 支持的延迟执行方法
local itemReloadFrame = CreateFrame("Frame")
itemReloadFrame:SetScript("OnUpdate", function(self, elapsed)
self.elapsed = (self.elapsed or 0) + elapsed
if self.elapsed >= 0.1 then
self:SetScript("OnUpdate", nil)
self:Hide()
-- 如果物品页面当前打开,刷新显示
if SM_Collections.MainFrame and SM_Collections.MainFrame.tabID == 4 then
-- 如果当前正在使用物品收藏UI
if SM_ItemCollectionUI and SM_ItemCollectionUI.currentPanel then
-- 如果有当前选中的按钮和对应的槽位数据
if SM_ItemCollectionUI.currentSelectedButton and SM_ItemCollectionUI.currentSelectedButton.slotData then
-- 对当前槽位的物品重新排序并刷新显示
local slot = SM_ItemCollectionUI.currentSelectedButton.slotData
SM_ItemCollectionUI:SortSlotItems(slot)
SM_ItemCollectionUI:ShowItemPreview(slot, SM_ItemCollectionUI.currentPanel)
end
end
-- 这里调用现有的显示物品函数
SM_Collections:ShowItems()
end
end
end)
itemReloadFrame:Show()
end
end
else
print("[收藏更新] 消息格式不正确:", msg)
end
end
-- 强制物品重排序,立即执行而不等待延迟
function SM_Collections:ForceItemReordering(updatedItemID)
-- 确保物品收藏UI存在
if not SM_ItemCollectionUI then
return
end
-- 确保物品槽位数据存在
if not SM_ItemCollectionUI.ALL_SLOTS then
return
end
-- 是否当前显示的是物品面板
local isItemPanelVisible = (SM_Collections.MainFrame and SM_Collections.MainFrame.tabID == 4)
-- 对所有槽位进行排序
local allSlots = SM_ItemCollectionUI.ALL_SLOTS
local targetSlot = nil
-- 找到包含更新物品的槽位
for _, slot in ipairs(allSlots) do
local containsItem = false
for _, itemID in ipairs(slot.items or {}) do
if tonumber(itemID) == tonumber(updatedItemID) then
targetSlot = slot
containsItem = true
break
end
end
-- 无论是否包含物品,都对该槽位进行排序
if #(slot.items or {}) > 0 then
SM_ItemCollectionUI:SortSlotItems(slot)
end
end
-- 如果物品面板可见,且找到了包含更新物品的槽位
if isItemPanelVisible and targetSlot then
-- 如果当前显示的正是包含更新物品的槽位
if SM_ItemCollectionUI.currentSelectedButton and
SM_ItemCollectionUI.currentSelectedButton.slotData and
SM_ItemCollectionUI.currentSelectedButton.slotData.invType == targetSlot.invType then
-- 直接重新显示物品预览
SM_ItemCollectionUI:ShowItemPreview(targetSlot, SM_ItemCollectionUI.currentPanel)
-- 强制立即重新加载整个物品面板
SM_Collections:ShowItems()
else
local currentSlot = SM_ItemCollectionUI.currentSelectedButton.slotData
SM_ItemCollectionUI:ShowItemPreview(currentSlot, SM_ItemCollectionUI.currentPanel)
end
end
end
-- 消息处理函数
function SM_Collections_MessageEvent(self, event, prefix, msg, type, sender)
if event == 'CHAT_MSG_WHISPER' or event == 'CHAT_MSG_ADDON' then
if prefix == 'SM_S_COLLECTIONS_MOUNTS' then
SM_Collections:HandleMountsData(msg) -- 坐骑
elseif prefix == 'SM_S_COLLECTIONS_COMPANIONS' then
SM_Collections:HandleCompanionsData(msg) -- 小伙伴
elseif prefix == 'SM_S_COLLECTIONS_CARDS' then
SM_Collections:HandleCardsData(msg) -- 卡牌
elseif prefix == 'SM_S_COLLECTIONS_ITEMS' then
SM_Collections:HandleItemsData(msg) -- 物品
elseif prefix == 'SM_S_COLLECTIONS_ATTRIBUTES' then
SM_Collections:HandleAttributesData(msg) -- 属性
elseif prefix == 'SM_S_COLLECTIONS_ITEM_ATTRIBUTES' then
SM_Collections:HandleItemAttributesData(msg) -- 物品属性
elseif prefix == "SM_S_COLLECTION_UPDATE" then
SM_Collections:HandleCollectionUpdate(msg)
end
end
end
-- 添加测试更新命令
SLASH_SM_COLLECTIONS_TEST1 = "/smtest"
SLASH_SM_COLLECTIONS_TEST2 = "/收藏测试"
SlashCmdList["SM_COLLECTIONS_TEST"] = function(msg)
-- 解析命令参数 /smtest item 12345 1
local args = {}
for word in msg:gmatch("%S+") do
table.insert(args, word)
end
local itemType = args[1] or "item"
local itemID = tonumber(args[2] or "12345")
local status = args[3] or "1"
-- 构造测试消息
local testMsg = itemType .. "|" .. itemID .. "|" .. status
-- 直接调用处理函数
SM_Collections:HandleCollectionUpdate(testMsg)
end
-- 事件监听框架
local SM_Collections_EventFrame = CreateFrame('Frame', 'SM_Collections_EventFrame')
SM_Collections_EventFrame:RegisterEvent('CHAT_MSG_WHISPER')
SM_Collections_EventFrame:RegisterEvent('CHAT_MSG_ADDON')
SM_Collections_EventFrame:RegisterEvent('ADDON_LOADED')
SM_Collections_EventFrame:SetScript('OnEvent', function(self, event, ...)
if event == 'ADDON_LOADED' then
local addonName = ...
if addonName == "SM_CollectionSystem" then
print("收藏系统插件加载完成")
end
elseif event == 'CHAT_MSG_ADDON' then
SM_Collections_MessageEvent(self, event, ...)
if not SM_Collections.MainFrame then
SM_Collections:CreateMainFrame()
-- 确保设置了默认的tabID
if SM_Collections.MainFrame then
SM_Collections.MainFrame.tabID = SM_Collections.MainFrame.tabID or 1
end
SM_Collections.MainFrame:Hide()
end
elseif event == 'CHAT_MSG_WHISPER' then
local msg, sender, _, _, _, _, _, _, _, _, _, guid, bnSenderID, isMobile, isSubtitle, hideSenderInLetterbox, supressRaidIcons = ...
-- 检查消息格式,判断是否是我们的插件消息
local prefix, content = strsplit("\t", msg, 2)
if content and (prefix == "SM_S_COLLECTIONS_MOUNTS" or
prefix == "SM_S_COLLECTIONS_COMPANIONS" or
prefix == "SM_S_COLLECTIONS_CARDS" or
prefix == "SM_S_COLLECTIONS_ITEMS" or
prefix == "SM_S_COLLECTIONS_ATTRIBUTES" or
prefix == "SM_S_COLLECTIONS_ITEM_ATTRIBUTES" or
prefix == "SM_S_COLLECTION_UPDATE") then
SM_Collections_MessageEvent(self, "CHAT_MSG_WHISPER", prefix, content)
end
end
end)