-- 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) 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 local data = self:MessageSplit(line, "|") -- 每4个元素为一组进行循环处理(属性名、属性值、属性类型、是否正面) for i = 1, #data, 4 do if data[i] and data[i + 1] and data[i + 2] and data[i + 3] then local attribute = { Name = data[i], value = tonumber(data[i + 1]), valueType = data[i + 2], isPositive = data[i + 3] == "1" -- 使用服务端发送的标志 } 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)