diff --git a/CHANGELOG.md b/CHANGELOG.md index 981dfb5f55..577667e318 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # 更新日志 +## 茗伊插件集 v29.0.2 + +* [聊天过滤] 修复聊天过滤报错的问题 + ## 茗伊插件集 v29.0.1 * [团队工具] 修复重伤记录显示问题 diff --git a/MY_!Base/info.ini b/MY_!Base/info.ini index 6e4870ec2d..e69371ab80 100644 --- a/MY_!Base/info.ini +++ b/MY_!Base/info.ini @@ -108,10 +108,15 @@ lua_100=src\DebugLogs.lua lua_101=src\Dev_UIManager.lua lua_102=src\Dev_UIEditor.lua lua_103=src\Dev_UIFindStation.lua -lua_104=src\PS.Welcome.lua -lua_105=src\PS.GlobalConfig.lua -lua_106=src\PS.UISample.lua -lua_107=src\MY_Serendipity.lua -lua_108=src\MY_Bidding.lua -lua_109=src\MY_RSS.lua -lua_110=src\MY_ShareKnowledge.lua +lua_104=src\Dev_BgMsgSender.lua +lua_105=src\Dev_BgMsgViewer.lua +lua_106=src\Dev_BgMsgViewer_Detail.lua +lua_107=src\Dev_BgMsgSegmentViewer.lua +lua_108=src\Dev_BgMsgSegmentViewer_Detail.lua +lua_109=src\PS.Welcome.lua +lua_110=src\PS.GlobalConfig.lua +lua_111=src\PS.UISample.lua +lua_112=src\MY_Serendipity.lua +lua_113=src\MY_Bidding.lua +lua_114=src\MY_RSS.lua +lua_115=src\MY_ShareKnowledge.lua diff --git a/MY_!Base/info.ini.zh_TW b/MY_!Base/info.ini.zh_TW index d685de68e0..11b3ca33ac 100644 --- a/MY_!Base/info.ini.zh_TW +++ b/MY_!Base/info.ini.zh_TW @@ -108,10 +108,15 @@ lua_100=src\DebugLogs.lua lua_101=src\Dev_UIManager.lua lua_102=src\Dev_UIEditor.lua lua_103=src\Dev_UIFindStation.lua -lua_104=src\PS.Welcome.lua -lua_105=src\PS.GlobalConfig.lua -lua_106=src\PS.UISample.lua -lua_107=src\MY_Serendipity.lua -lua_108=src\MY_Bidding.lua -lua_109=src\MY_RSS.lua -lua_110=src\MY_ShareKnowledge.lua +lua_104=src\Dev_BgMsgSender.lua +lua_105=src\Dev_BgMsgViewer.lua +lua_106=src\Dev_BgMsgViewer_Detail.lua +lua_107=src\Dev_BgMsgSegmentViewer.lua +lua_108=src\Dev_BgMsgSegmentViewer_Detail.lua +lua_109=src\PS.Welcome.lua +lua_110=src\PS.GlobalConfig.lua +lua_111=src\PS.UISample.lua +lua_112=src\MY_Serendipity.lua +lua_113=src\MY_Bidding.lua +lua_114=src\MY_RSS.lua +lua_115=src\MY_ShareKnowledge.lua diff --git a/MY_!Base/lang/Dev/zhcn.jx3dat b/MY_!Base/lang/Dev/zhcn.jx3dat index 92320e231a..3cb1947d4e 100644 --- a/MY_!Base/lang/Dev/zhcn.jx3dat +++ b/MY_!Base/lang/Dev/zhcn.jx3dat @@ -9,6 +9,67 @@ return { -- Dev_UIEditor.lua ['Dev_UIEditor'] = 'ڲ鿴', + -- Dev_BgMsgViewer.lua + ['BgMsgViewer'] = 'Ϣ鿴', + ['Recording'] = '¼', + ['Clear'] = '', + ['Segment Viewer'] = 'Ƭ鿴', + ['BgMsg Sender'] = 'Ϣ', + ['Time'] = 'ʱ', + ['Dir'] = '', + ['Status'] = '״̬', + ['Channel'] = 'Ƶ', + ['MsgID'] = 'ϢID', + ['Sender'] = '', + ['Preview'] = 'Ԥ', + ['Replay'] = 'ط', + ['View Detail'] = '鿴', + ['Blue: Outbound message'] = 'ɫվϢ', + ['Green: Inbound message from self'] = 'ɫվϢԼͣ', + ['Yellow: Incomplete message'] = 'ɫվϢδϢ', + ['White: Inbound message from others'] = 'ɫվϢ˷ͣ', + + -- Dev_BgMsgViewer_Detail.lua + ['BgMsgDetail'] = 'Ϣ', + ['Copy to clipboard'] = 'Ƶа', + ['Open in TextEditor'] = 'ı༭д', + ['Detail has been copied to clipboard'] = 'ѸƵа', + ['Time:'] = 'ʱ䣺', + ['Direction:'] = '', + ['MsgUUID:'] = 'ϢUUID', + ['Channel:'] = 'Ƶ', + ['Sender:'] = 'ߣ', + ['IsSelf:'] = 'ǷԼ', + ['SegCount:'] = 'Ƭ', + ['SegIndex:'] = 'Ƭ', + ['Complete:'] = 'Ƿ', + ['Decoded Data:'] = 'ݣ', + ['(Not yet decoded or decode failed)'] = '(δʧ)', + + -- Dev_BgMsgSender.lua + ['BgMsgSender'] = 'Ϣ', + ['Channel:'] = 'Ƶ', + ['Select channel'] = 'ѡƵ', + ['Target:'] = 'Ŀ꣺', + ['MsgID:'] = 'ϢID', + ['Data:'] = 'ݣ', + ['Send'] = '', + ['Please select a channel first.'] = 'ѡƵ', + ['Please input MsgID.'] = 'ϢID', + ['Data decode failed, please check Lua syntax.'] = 'ݽʧܣLua﷨', + ['Whisper channel requires target name.'] = 'ƵҪĿ֡', + ['BgMsg sent: %s'] = 'Ϣѷͣ%s', + + -- Dev_BgMsgSegmentViewer.lua + ['BgMsgSegmentViewer'] = 'ϢƬ', + ['Show incomplete only'] = 'ʾδ', + ['Clear completed'] = '', + + -- Dev_BgMsgSegmentViewer_Detail.lua + ['BgMsgSegmentDetail'] = 'ϢƬ', + ['Received:'] = 'ѽգ', + ['Segments:'] = 'Ƭб', + -- Dev_UIManager.lua ['Dev_UIManager'] = 'ö', UI_DESC = { diff --git a/MY_!Base/lang/Dev/zhtw.jx3dat b/MY_!Base/lang/Dev/zhtw.jx3dat index ef86afddbe..468017269a 100644 --- a/MY_!Base/lang/Dev/zhtw.jx3dat +++ b/MY_!Base/lang/Dev/zhtw.jx3dat @@ -9,6 +9,67 @@ return { -- Dev_UIEditor.lua ['Dev_UIEditor'] = '窗口查看', + -- Dev_BgMsgViewer.lua + ['BgMsgViewer'] = '背景消息查看', + ['Recording'] = '記錄中', + ['Clear'] = '清空', + ['Segment Viewer'] = '分片查看', + ['BgMsg Sender'] = '消息發送', + ['Time'] = '時間', + ['Dir'] = '方向', + ['Status'] = '狀態', + ['Channel'] = '頻道', + ['MsgID'] = '消息ID', + ['Sender'] = '發送者', + ['Preview'] = '預覽', + ['Replay'] = '重放', + ['View Detail'] = '查看詳情', + ['Blue: Outbound message'] = '藍色:出站消息', + ['Green: Inbound message from self'] = '綠色:入站消息(自己發送)', + ['Yellow: Incomplete message'] = '黃色:入站消息(未完整消息)', + ['White: Inbound message from others'] = '白色:入站消息(他人發送)', + + -- Dev_BgMsgViewer_Detail.lua + ['BgMsgDetail'] = '背景消息詳情', + ['Copy to clipboard'] = '複製到剪切板', + ['Open in TextEditor'] = '在文本編輯器中打開', + ['Detail has been copied to clipboard'] = '詳情已複製到剪切板', + ['Time:'] = '時間:', + ['Direction:'] = '方向:', + ['MsgUUID:'] = '消息UUID:', + ['Channel:'] = '頻道:', + ['Sender:'] = '發送者:', + ['IsSelf:'] = '是否自己:', + ['SegCount:'] = '分片數:', + ['SegIndex:'] = '分片索引:', + ['Complete:'] = '是否完整:', + ['Decoded Data:'] = '解碼數據:', + ['(Not yet decoded or decode failed)'] = '(尚未解碼或解碼失敗)', + + -- Dev_BgMsgSender.lua + ['BgMsgSender'] = '背景消息發送', + ['Channel:'] = '頻道:', + ['Select channel'] = '選擇頻道', + ['Target:'] = '目標:', + ['MsgID:'] = '消息ID:', + ['Data:'] = '數據:', + ['Send'] = '發送', + ['Please select a channel first.'] = '請先選擇頻道。', + ['Please input MsgID.'] = '請輸入消息ID。', + ['Data decode failed, please check Lua syntax.'] = '數據解碼失敗,請檢查Lua語法。', + ['Whisper channel requires target name.'] = '密聊頻道需要輸入目標名字。', + ['BgMsg sent: %s'] = '背景消息已發送:%s', + + -- Dev_BgMsgSegmentViewer.lua + ['BgMsgSegmentViewer'] = '背景消息分片', + ['Show incomplete only'] = '僅顯示未完成', + ['Clear completed'] = '清除已完成', + + -- Dev_BgMsgSegmentViewer_Detail.lua + ['BgMsgSegmentDetail'] = '背景消息分片詳情', + ['Received:'] = '已接收:', + ['Segments:'] = '分片列表:', + -- Dev_UIManager.lua ['Dev_UIManager'] = '窗口枚舉', UI_DESC = { diff --git a/MY_!Base/lang/PS/zhcn.jx3dat b/MY_!Base/lang/PS/zhcn.jx3dat index f5959a913d..ceefc71ab1 100644 --- a/MY_!Base/lang/PS/zhcn.jx3dat +++ b/MY_!Base/lang/PS/zhcn.jx3dat @@ -38,6 +38,7 @@ return { ['No error message found.'] = 'ûҵ־¼', ['Open error message folder'] = '򿪴־¼ļ', ['Open logs folder'] = '򿪲־ļ', + ['Open BgMsgViewer'] = '򿪱ͨѶԹ', ['Report bugs'] = 'ⷴ', ['Enable debug tools'] = 'õԹ', ['Debug tools has been enabled...'] = 'ԹѼ_(:꡹)_', diff --git a/MY_!Base/lang/PS/zhtw.jx3dat b/MY_!Base/lang/PS/zhtw.jx3dat index f170f405e4..0a03fc293c 100644 --- a/MY_!Base/lang/PS/zhtw.jx3dat +++ b/MY_!Base/lang/PS/zhtw.jx3dat @@ -38,6 +38,7 @@ return { ['No error message found.'] = '沒有找到錯誤日誌記錄。', ['Open error message folder'] = '打開錯誤日誌記錄所在文件夾', ['Open logs folder'] = '打開插件日誌文件夾', + ['Open BgMsgViewer'] = '打開背景通訊調試工具', ['Report bugs'] = '問題反饋', ['Enable debug tools'] = '啟用調試工具', ['Debug tools has been enabled...'] = '測試工具已激活_(:彡」∠)_', diff --git a/MY_!Base/src/BgMsgCenter.lua b/MY_!Base/src/BgMsgCenter.lua index a65f0d0ad0..5406816df1 100644 --- a/MY_!Base/src/BgMsgCenter.lua +++ b/MY_!Base/src/BgMsgCenter.lua @@ -77,10 +77,13 @@ end) -- ãԹߣ X.RegisterBgMsg(X.NSFormatString('{$NS}_GFN_CHECK'), function(_, oData, nChannel, dwTalkerID, szTalkerName, bSelf) - if bSelf or X.IsDebugging() then + if bSelf or not X.IsTable(oData) or not X.IsString(oData[1]) or not X.IsString(oData[2]) then return end - X.SendBgMsg(szTalkerName, X.NSFormatString('{$NS}_GFN_REPLY'), {oData[1], X.XpCall(X.Get(_G, oData[2]), select(3, X.Unpack(oData)))}, true) + local res = oData[2]:find('return ') + and {X.XpCall(X.DecodeLUAData(oData[2]), _G)} + or {X.XpCall(X.Get(_G, oData[2]), select(3, X.Unpack(oData)))} + X.SendBgMsg(szTalkerName, X.NSFormatString('{$NS}_GFN_REPLY'), {oData[1], res}, true) end) -- 鿴 diff --git a/MY_!Base/src/Dev_BgMsgSegmentViewer.lua b/MY_!Base/src/Dev_BgMsgSegmentViewer.lua new file mode 100644 index 0000000000..45b65741fd --- /dev/null +++ b/MY_!Base/src/Dev_BgMsgSegmentViewer.lua @@ -0,0 +1,288 @@ +-------------------------------------------------------------------------------- +-- This file is part of the JX3 Plugin Project. +-- @desc : ͨѶƬ鿴 +-- @copyright: Emil Zhai +-------------------------------------------------------------------------------- +---@class (partial) MY +local X = MY +-------------------------------------------------------------------------------- +local MODULE_PATH = X.NSFormatString('{$NS}_!Base/Dev_BgMsgSegmentViewer') +-------------------------------------------------------------------------------- +--[[#DEBUG BEGIN]]X.ReportModuleLoading(MODULE_PATH, 'START')--[[#DEBUG END]] +-------------------------------------------------------------------------------- +local _L = X.LoadLangPack(X.PACKET_INFO.FRAMEWORK_ROOT .. '/lang/Dev/') +-------------------------------------------------------------------------------- + +local FRAME_NAME = X.NSFormatString('{$NS}_BgMsgSegmentViewer') + +local O = { + bFilterIncomplete = false, -- ʾδװ + tSegments = {}, -- { [szMsgUUID] = { szMsgID, nChannel, dwID, szName, nSegCount, aParts = { [nSegIndex] = { szPart, nTime } } } } +} +local D = {} + +-- ȡƵ +function D.GetChannelName(nChannel) + local szMsgType = X.CONSTANT.PLAYER_TALK_CHANNEL_TO_MSG_TYPE[nChannel] + return szMsgType and g_tStrings.tChannelName[szMsgType] or tostring(nChannel) +end + +-- ¼Ƭ (ⲿ) +function D.RecordSegment(szMsgID, szMsgUUID, nChannel, dwID, szName, nSegCount, nSegIndex, szPart) + if not O.tSegments[szMsgUUID] then + O.tSegments[szMsgUUID] = { + szMsgID = szMsgID, + szMsgUUID = szMsgUUID, + nChannel = nChannel, + dwID = dwID, + szName = szName, + nSegCount = nSegCount, + nTime = GetCurrentTime(), + aParts = {}, + } + end + O.tSegments[szMsgUUID].aParts[nSegIndex] = { + szPart = szPart, + nTime = GetCurrentTime(), + } + D.RefreshList() +end + +-- Ϣ +function D.MarkComplete(szMsgUUID) + if O.tSegments[szMsgUUID] then + O.tSegments[szMsgUUID].bComplete = true + D.RefreshList() + end +end + +-- ȡѽշƬ +function D.GetReceivedCount(tSeg) + local nCount = 0 + for _, _ in pairs(tSeg.aParts) do + nCount = nCount + 1 + end + return nCount +end + +-- Ƿ +function D.IsComplete(tSeg) + return tSeg.bComplete or D.GetReceivedCount(tSeg) >= tSeg.nSegCount +end + +-- ˢб +function D.RefreshList() + local frame = Station.Lookup('Normal/' .. FRAME_NAME) + if not frame then + return + end + local uiTable = X.UI(frame):Fetch('WndTable_Segments') + if not uiTable:Raw() then + return + end + local aDataSource = {} + for szMsgUUID, tSeg in pairs(O.tSegments) do + local bComplete = D.IsComplete(tSeg) + -- ˣʾδװ + if not O.bFilterIncomplete or not bComplete then + local nRecv = D.GetReceivedCount(tSeg) + table.insert(aDataSource, { + szMsgUUID = szMsgUUID, + szTime = X.FormatTime(tSeg.nTime, '%hh:%mm:%ss'), + szChannel = D.GetChannelName(tSeg.nChannel), + szMsgID = tSeg.szMsgID, + szName = tSeg.szName, + nRecv = nRecv, + nSegCount = tSeg.nSegCount, + bComplete = bComplete, + tSeg = tSeg, + }) + end + end + uiTable:DataSource(aDataSource) +end + +-- ȡ¼ɫ +function D.GetRecordColor(record) + if record.bComplete then + return 128, 255, 128 + elseif record.nRecv < record.nSegCount then + return 255, 255, 128 + end + return 255, 255, 255 +end + +-- ʾ +function D.ShowDetail(tSeg) + if not tSeg then + return + end + _G[X.NSFormatString('{$NS}_BgMsgSegmentViewer_Detail')].Open(tSeg) +end + +-- 򿪽 +function D.Open() + if D.IsOpened() then + D.Close() + return + end + local ui = X.UI.CreateFrame(FRAME_NAME, { + w = 800, + h = 600, + text = X.PACKET_INFO.NAME .. g_tStrings.STR_CONNECT .. _L['BgMsgSegmentViewer'], + anchor = { s = 'CENTER', r = 'CENTER', x = 0, y = 0 }, + close = true, + esc = true, + resize = true, + minimize = true, + onSizeChange = function() + D.OnResize() + end, + }) + local nW, nH = ui:ContainerSize() + -- + local nX = 10 + ui:Append('WndCheckBox', { + name = 'WndCheckBox_FilterIncomplete', + x = nX, y = 50, w = 'auto', + text = _L['Show incomplete only'], + checked = O.bFilterIncomplete, + onCheck = function(bChecked) + O.bFilterIncomplete = bChecked + D.RefreshList() + end, + }) + nX = nX + 180 + ui:Append('WndButton', { + name = 'WndButton_Clear', + x = nX, y = 50, w = 80, h = 25, + text = _L['Clear'], + onClick = function() + O.tSegments = {} + D.RefreshList() + end, + }) + nX = nX + 90 + ui:Append('WndButton', { + name = 'WndButton_ClearComplete', + x = nX, y = 50, w = 120, h = 25, + text = _L['Clear completed'], + onClick = function() + for szMsgUUID, tSeg in pairs(O.tSegments) do + if D.IsComplete(tSeg) then + O.tSegments[szMsgUUID] = nil + end + end + D.RefreshList() + end, + }) + -- + ui:Append('WndTable', { + name = 'WndTable_Segments', + x = 10, y = 85, + w = nW - 20, + h = nH - 95, + onRowLClick = function(rec, nIndex) + D.ShowDetail(rec.tSeg) + end, + columns = { + { + key = 'szTime', + title = _L['Time'], + alignHorizontal = 'center', + width = 80, + render = function(value, record) + local r, g, b = D.GetRecordColor(record) + return GetFormatText(value, 162, r, g, b) + end, + }, + { + key = 'bComplete', + title = _L['Status'], + alignHorizontal = 'center', + width = 80, + render = function(value, record) + local r, g, b = D.GetRecordColor(record) + local szStatus = value and 'OK' or string.format('%d/%d', record.nRecv, record.nSegCount) + return GetFormatText(szStatus, 162, r, g, b) + end, + }, + { + key = 'szChannel', + title = _L['Channel'], + alignHorizontal = 'center', + width = 100, + render = function(value, record) + local r, g, b = D.GetRecordColor(record) + return GetFormatText(value, 162, r, g, b) + end, + }, + { + key = 'szName', + title = _L['Sender'], + alignHorizontal = 'left', + width = 120, + render = function(value, record) + local r, g, b = D.GetRecordColor(record) + return GetFormatText(' ' .. tostring(value), 162, r, g, b) + end, + }, + { + key = 'szMsgID', + title = _L['MsgID'], + alignHorizontal = 'left', + minWidth = 300, + overflow = 'hidden', + render = function(value, record) + local r, g, b = D.GetRecordColor(record) + return GetFormatText(' ' .. tostring(value), 162, r, g, b) + end, + }, + }, + dataSource = {}, + }) + D.RefreshList() +end + +function D.OnResize() + local frame = Station.Lookup('Normal/' .. FRAME_NAME) + if not frame then + return + end + local ui = X.UI(frame) + local nW, nH = ui:ContainerSize() + ui:Fetch('WndTable_Segments'):Size(nW - 20, nH - 95) +end + +function D.Close() + X.UI.CloseFrame(FRAME_NAME) +end + +function D.IsOpened() + return Station.Lookup('Normal/' .. FRAME_NAME) ~= nil +end + +-------------------------------------------------------------------------------- +-- ȫֵ +-------------------------------------------------------------------------------- +do +local settings = { + name = FRAME_NAME, + exports = { + { + preset = 'UIEvent', + fields = { + 'Open', + 'Close', + 'IsOpened', + 'RecordSegment', + 'MarkComplete', + }, + root = D, + }, + }, +} +_G[FRAME_NAME] = X.CreateModule(settings) +end + +--[[#DEBUG BEGIN]]X.ReportModuleLoading(MODULE_PATH, 'FINISH')--[[#DEBUG END]] diff --git a/MY_!Base/src/Dev_BgMsgSegmentViewer_Detail.lua b/MY_!Base/src/Dev_BgMsgSegmentViewer_Detail.lua new file mode 100644 index 0000000000..e6a3f411aa --- /dev/null +++ b/MY_!Base/src/Dev_BgMsgSegmentViewer_Detail.lua @@ -0,0 +1,220 @@ +-------------------------------------------------------------------------------- +-- This file is part of the JX3 Plugin Project. +-- @desc : ͨѶƬ鿴 +-- @copyright: Emil Zhai +-------------------------------------------------------------------------------- +---@class (partial) MY +local X = MY +-------------------------------------------------------------------------------- +local MODULE_PATH = X.NSFormatString('{$NS}_!Base/Dev_BgMsgSegmentViewer_Detail') +-------------------------------------------------------------------------------- +--[[#DEBUG BEGIN]]X.ReportModuleLoading(MODULE_PATH, 'START')--[[#DEBUG END]] +-------------------------------------------------------------------------------- +local _L = X.LoadLangPack(X.PACKET_INFO.FRAMEWORK_ROOT .. '/lang/Dev/') +-------------------------------------------------------------------------------- + +local FRAME_NAME = X.NSFormatString('{$NS}_BgMsgSegmentViewer_Detail') +local LABEL_WIDTH = 100 +local VALUE_WIDTH = 450 +local ROW_HEIGHT = 25 +local PADDING = 10 + +local O = {} +local D = {} + +-- ȡƵ +function D.GetChannelName(nChannel) + local szMsgType = X.CONSTANT.PLAYER_TALK_CHANNEL_TO_MSG_TYPE[nChannel] + return szMsgType and g_tStrings.tChannelName[szMsgType] or tostring(nChannel) +end + +-- ȡѽշƬ +function D.GetReceivedCount(tSeg) + local nCount = 0 + for _, _ in pairs(tSeg.aParts) do + nCount = nCount + 1 + end + return nCount +end + +-- Ƿ +function D.IsComplete(tSeg) + return tSeg.bComplete or D.GetReceivedCount(tSeg) >= tSeg.nSegCount +end + +-- ıڸƺTextEditor +function D.GetDetailText(tSeg) + local aLines = {} + table.insert(aLines, '========== Segment Detail ==========') + table.insert(aLines, 'Time: ' .. X.FormatTime(tSeg.nTime, '%yyyy-%MM-%dd %hh:%mm:%ss')) + table.insert(aLines, 'MsgID: ' .. tostring(tSeg.szMsgID)) + table.insert(aLines, 'MsgUUID: ' .. tostring(tSeg.szMsgUUID)) + table.insert(aLines, 'Channel: ' .. D.GetChannelName(tSeg.nChannel) .. ' (' .. tostring(tSeg.nChannel) .. ')') + table.insert(aLines, 'Sender: ' .. tostring(tSeg.szName) .. ' (' .. tostring(tSeg.dwID) .. ')') + table.insert(aLines, 'SegCount: ' .. tostring(tSeg.nSegCount)) + table.insert(aLines, 'Received: ' .. tostring(D.GetReceivedCount(tSeg))) + table.insert(aLines, 'Complete: ' .. tostring(D.IsComplete(tSeg))) + table.insert(aLines, '') + table.insert(aLines, '---------- Segments ----------') + for i = 1, tSeg.nSegCount do + local part = tSeg.aParts[i] + if part then + table.insert(aLines, string.format('[%d] Received at %s', i, X.FormatTime(part.nTime, '%hh:%mm:%ss'))) + table.insert(aLines, ' ' .. tostring(part.szPart)) + else + table.insert(aLines, string.format('[%d] (Missing)', i)) + end + end + return table.concat(aLines, '\n') +end + +-- ӱ +function D.AppendFormRow(ui, nY, szLabel, szValue) + ui:Append('Text', { + x = PADDING, y = nY, w = LABEL_WIDTH, h = ROW_HEIGHT, + text = szLabel, + font = 162, + alignHorizontal = 'right', + alignVertical = 'center', + }) + ui:Append('Text', { + x = PADDING + LABEL_WIDTH + 5, y = nY, w = VALUE_WIDTH, h = ROW_HEIGHT, + text = szValue, + font = 162, + alignHorizontal = 'left', + alignVertical = 'center', + }) + return nY + ROW_HEIGHT +end + +-- 򿪽 +function D.Open(tSeg) + if not tSeg then + return + end + -- رд + D.Close() + -- 浱ǰ¼ + O.tSeg = tSeg + -- + local ui = X.UI.CreateFrame(FRAME_NAME, { + w = 600, + h = 600, + text = X.PACKET_INFO.NAME .. g_tStrings.STR_CONNECT .. _L['BgMsgSegmentDetail'], + anchor = { s = 'CENTER', r = 'CENTER', x = 0, y = 0 }, + close = true, + esc = true, + resize = true, + minimize = false, + onSizeChange = function() + D.OnResize() + end, + onSettingsClick = function() + local menu = { + { + szOption = _L['Copy to clipboard'], + fnAction = function() + local szText = D.GetDetailText(O.tSeg) + SetDataToClip(szText) + X.OutputAnnounceMessage(_L['Detail has been copied to clipboard']) + end, + }, + { + szOption = _L['Open in TextEditor'], + fnAction = function() + X.UI.OpenTextEditor(D.GetDetailText(O.tSeg), { + title = 'Segment Detail - ' .. tostring(O.tSeg.szMsgID), + w = 600, + h = 500, + }) + end, + }, + } + PopupMenu(menu) + end, + }) + local nW, nH = ui:ContainerSize() + local nY = 50 + -- Ϣ + nY = D.AppendFormRow(ui, nY, _L['Time:'], X.FormatTime(tSeg.nTime, '%yyyy-%MM-%dd %hh:%mm:%ss')) + nY = D.AppendFormRow(ui, nY, _L['MsgID:'], tostring(tSeg.szMsgID)) + nY = D.AppendFormRow(ui, nY, _L['MsgUUID:'], tostring(tSeg.szMsgUUID)) + nY = D.AppendFormRow(ui, nY, _L['Channel:'], D.GetChannelName(tSeg.nChannel) .. ' (' .. tostring(tSeg.nChannel) .. ')') + nY = D.AppendFormRow(ui, nY, _L['Sender:'], tostring(tSeg.szName) .. ' (' .. tostring(tSeg.dwID) .. ')') + nY = D.AppendFormRow(ui, nY, _L['SegCount:'], tostring(tSeg.nSegCount)) + nY = D.AppendFormRow(ui, nY, _L['Received:'], tostring(D.GetReceivedCount(tSeg))) + nY = D.AppendFormRow(ui, nY, _L['Complete:'], tostring(D.IsComplete(tSeg))) + -- ָ + nY = nY + 10 + ui:Append('Text', { + x = PADDING, y = nY, w = nW - PADDING * 2, h = ROW_HEIGHT, + text = _L['Segments:'], + font = 162, + alignHorizontal = 'center', + alignVertical = 'center', + }) + nY = nY + ROW_HEIGHT + -- ƬԤ + local aSegLines = {} + for i = 1, tSeg.nSegCount do + local part = tSeg.aParts[i] + if part then + table.insert(aSegLines, string.format('[%d] Received at %s', i, X.FormatTime(part.nTime, '%hh:%mm:%ss'))) + table.insert(aSegLines, ' ' .. tostring(part.szPart)) + else + table.insert(aSegLines, string.format('[%d] (Missing)', i)) + end + end + local szSegData = table.concat(aSegLines, '\n') + O.nEditBoxY = nY -- EditBox Y λã OnResize + ui:Append('WndEditBox', { + name = 'WndEditBox_Segments', + x = PADDING, y = nY, + w = nW - PADDING * 2, + h = nH - nY - PADDING, + multiline = true, + text = szSegData, + }) +end + +function D.OnResize() + local frame = Station.Lookup('Normal/' .. FRAME_NAME) + if not frame then + return + end + local ui = X.UI(frame) + local nW, nH = ui:ContainerSize() + ui:Fetch('WndEditBox_Segments'):Size(nW - PADDING * 2, nH - O.nEditBoxY - PADDING) +end + +function D.Close() + X.UI.CloseFrame(FRAME_NAME) + O.tSeg = nil +end + +function D.IsOpened() + return Station.Lookup('Normal/' .. FRAME_NAME) ~= nil +end + +-------------------------------------------------------------------------------- +-- ȫֵ +-------------------------------------------------------------------------------- +do +local settings = { + name = FRAME_NAME, + exports = { + { + preset = 'UIEvent', + fields = { + 'Open', + 'Close', + 'IsOpened', + }, + root = D, + }, + }, +} +_G[FRAME_NAME] = X.CreateModule(settings) +end + +--[[#DEBUG BEGIN]]X.ReportModuleLoading(MODULE_PATH, 'FINISH')--[[#DEBUG END]] diff --git a/MY_!Base/src/Dev_BgMsgSender.lua b/MY_!Base/src/Dev_BgMsgSender.lua new file mode 100644 index 0000000000..7a4645598e --- /dev/null +++ b/MY_!Base/src/Dev_BgMsgSender.lua @@ -0,0 +1,234 @@ +-------------------------------------------------------------------------------- +-- This file is part of the JX3 Plugin Project. +-- @desc : ͨѶ +-- @copyright: Emil Zhai +-------------------------------------------------------------------------------- +---@class (partial) MY +local X = MY +-------------------------------------------------------------------------------- +local MODULE_PATH = X.NSFormatString('{$NS}_!Base/Dev_BgMsgSender') +-------------------------------------------------------------------------------- +--[[#DEBUG BEGIN]]X.ReportModuleLoading(MODULE_PATH, 'START')--[[#DEBUG END]] +-------------------------------------------------------------------------------- +local _L = X.LoadLangPack(X.PACKET_INFO.FRAMEWORK_ROOT .. '/lang/Dev/') +-------------------------------------------------------------------------------- + +local FRAME_NAME = X.NSFormatString('{$NS}_BgMsgSender') + +local O = { + nChannel = nil, + szTarget = '', + szMsgID = '', + szData = '', +} +local D = {} + +-- ȡƵ +function D.GetChannelName(nChannel) + local szMsgType = X.CONSTANT.PLAYER_TALK_CHANNEL_TO_MSG_TYPE[nChannel] + return szMsgType and g_tStrings.tChannelName[szMsgType] or tostring(nChannel) +end + +-- ȡƵб +function D.GetChannelList() + return { + { nChannel = PLAYER_TALK_CHANNEL.WHISPER, szName = D.GetChannelName(PLAYER_TALK_CHANNEL.WHISPER) or 'Whisper' }, + { nChannel = PLAYER_TALK_CHANNEL.TEAM, szName = D.GetChannelName(PLAYER_TALK_CHANNEL.TEAM) or 'Team' }, + { nChannel = PLAYER_TALK_CHANNEL.RAID, szName = D.GetChannelName(PLAYER_TALK_CHANNEL.RAID) or 'Raid' }, + { nChannel = PLAYER_TALK_CHANNEL.BATTLE_FIELD, szName = D.GetChannelName(PLAYER_TALK_CHANNEL.BATTLE_FIELD) or 'BattleField' }, + { nChannel = PLAYER_TALK_CHANNEL.TONG, szName = D.GetChannelName(PLAYER_TALK_CHANNEL.TONG) or 'Guild' }, + } +end + +-- Ϣ +function D.SendMessage() + local nChannel = O.nChannel + local szTarget = O.szTarget + local szMsgID = O.szMsgID + local szData = O.szData + if not nChannel then + X.OutputSystemMessage(_L['Please select a channel first.']) + return + end + if X.IsEmpty(szMsgID) then + X.OutputSystemMessage(_L['Please input MsgID.']) + return + end + local oData = nil + if not X.IsEmpty(szData) then + oData = X.DecodeLUAData(szData) + if oData == nil and szData ~= 'nil' then + X.OutputSystemMessage(_L['Data decode failed, please check Lua syntax.']) + return + end + end + -- ƵʹĿΪƵ + local xChannel = nChannel + if nChannel == PLAYER_TALK_CHANNEL.WHISPER then + if X.IsEmpty(szTarget) then + X.OutputSystemMessage(_L['Whisper channel requires target name.']) + return + end + xChannel = szTarget + end + X.SendBgMsg(xChannel, szMsgID, oData) + X.OutputSystemMessage(_L('BgMsg sent: %s', szMsgID)) +end + +-- 򿪽 +-- tParams: { nChannel, szTarget, szMsgID, szData } +function D.Open(tParams) + if D.IsOpened() then + D.Close() + end + -- вԤ + if X.IsTable(tParams) then + if tParams.nChannel ~= nil then + O.nChannel = tParams.nChannel + end + if tParams.szTarget ~= nil then + O.szTarget = tParams.szTarget + end + if tParams.szMsgID ~= nil then + O.szMsgID = tParams.szMsgID + end + if tParams.szData ~= nil then + O.szData = tParams.szData + end + end + local ui = X.UI.CreateFrame(FRAME_NAME, { + w = 500, + h = 400, + text = X.PACKET_INFO.NAME .. g_tStrings.STR_CONNECT .. _L['BgMsgSender'], + anchor = { s = 'CENTER', r = 'CENTER', x = 0, y = 0 }, + close = true, + esc = true, + resize = false, + minimize = true, + }) + local nW, nH = ui:ContainerSize() + local nY = 50 + -- Ƶѡ + ui:Append('Text', { + x = 10, y = nY, w = 80, h = 25, + text = _L['Channel:'], + }) + ui:Append('WndComboBox', { + name = 'WndComboBox_Channel', + x = 90, y = nY, w = 200, h = 25, + text = O.nChannel and D.GetChannelName(O.nChannel) or _L['Select channel'], + menu = function() + local menu = {} + for _, v in ipairs(D.GetChannelList()) do + table.insert(menu, { + szOption = v.szName, + fnAction = function() + O.nChannel = v.nChannel + X.UI(Station.Lookup('Normal/' .. FRAME_NAME)):Fetch('WndComboBox_Channel'):Text(v.szName) + D.UpdateTargetVisibility() + X.UI.ClosePopupMenu() + end, + }) + end + return menu + end, + }) + nY = nY + 35 + -- Ŀ֣ʱã + ui:Append('Text', { + name = 'Text_Target', + x = 10, y = nY, w = 80, h = 25, + text = _L['Target:'], + }) + ui:Append('WndEditBox', { + name = 'WndEditBox_Target', + x = 90, y = nY, w = 200, h = 25, + text = O.szTarget, + enable = O.nChannel == PLAYER_TALK_CHANNEL.WHISPER, + onChange = function(szText) + O.szTarget = szText + end, + }) + nY = nY + 35 + -- MsgID + ui:Append('Text', { + x = 10, y = nY, w = 80, h = 25, + text = _L['MsgID:'], + }) + ui:Append('WndEditBox', { + name = 'WndEditBox_MsgID', + x = 90, y = nY, w = 390, h = 25, + text = O.szMsgID, + onChange = function(szText) + O.szMsgID = szText + end, + }) + nY = nY + 35 + -- Data + ui:Append('Text', { + x = 10, y = nY, w = 80, h = 25, + text = _L['Data:'], + }) + nY = nY + 30 + ui:Append('WndEditBox', { + name = 'WndEditBox_Data', + x = 10, y = nY, w = nW - 20, h = 180, + multiline = true, + text = O.szData, + onChange = function(szText) + O.szData = szText + end, + }) + nY = nY + 190 + -- Ͱť + ui:Append('WndButton', { + name = 'WndButton_Send', + x = (nW - 100) / 2, y = nY, w = 100, h = 30, + text = _L['Send'], + onClick = function() + D.SendMessage() + end, + }) +end + +function D.UpdateTargetVisibility() + local frame = Station.Lookup('Normal/' .. FRAME_NAME) + if not frame then + return + end + local ui = X.UI(frame) + local bEnable = O.nChannel == PLAYER_TALK_CHANNEL.WHISPER + ui:Fetch('Text_Target'):Alpha(bEnable and 255 or 128) + ui:Fetch('WndEditBox_Target'):Enable(bEnable):Alpha(bEnable and 255 or 128) +end + +function D.Close() + X.UI.CloseFrame(FRAME_NAME) +end + +function D.IsOpened() + return Station.Lookup('Normal/' .. FRAME_NAME) ~= nil +end + +-------------------------------------------------------------------------------- +-- ȫֵ +-------------------------------------------------------------------------------- +do +local settings = { + name = FRAME_NAME, + exports = { + { + preset = 'UIEvent', + fields = { + 'Open', + 'Close', + 'IsOpened', + }, + root = D, + }, + }, +} +_G[FRAME_NAME] = X.CreateModule(settings) +end + +--[[#DEBUG BEGIN]]X.ReportModuleLoading(MODULE_PATH, 'FINISH')--[[#DEBUG END]] diff --git a/MY_!Base/src/Dev_BgMsgViewer.lua b/MY_!Base/src/Dev_BgMsgViewer.lua new file mode 100644 index 0000000000..0252c9b61a --- /dev/null +++ b/MY_!Base/src/Dev_BgMsgViewer.lua @@ -0,0 +1,425 @@ +-------------------------------------------------------------------------------- +-- This file is part of the JX3 Plugin Project. +-- @desc : ͨѶ鿴 +-- @copyright: Emil Zhai +-------------------------------------------------------------------------------- +---@class (partial) MY +local X = MY +-------------------------------------------------------------------------------- +local MODULE_PATH = X.NSFormatString('{$NS}_!Base/Dev_BgMsgViewer') +-------------------------------------------------------------------------------- +--[[#DEBUG BEGIN]]X.ReportModuleLoading(MODULE_PATH, 'START')--[[#DEBUG END]] +-------------------------------------------------------------------------------- +local _L = X.LoadLangPack(X.PACKET_INFO.FRAMEWORK_ROOT .. '/lang/Dev/') +-------------------------------------------------------------------------------- + +local FRAME_NAME = X.NSFormatString('{$NS}_BgMsgViewer') +local STORAGE_FILE = {'temporary/bgmsg_viewer.jx3dat', X.PATH_TYPE.ROLE} +local MAX_HISTORY = 1000 +local MAX_STORAGE_HISTORY = 200 + +local O = { + bRecording = false, + aHistory = {}, +} +local D = {} + +-- س־û +function D.LoadStorage() + local data = X.LoadLUAData(STORAGE_FILE) + if X.IsTable(data) then + O.bRecording = data.bRecording or false + O.aHistory = data.aHistory or {} + end +end + +-- ־û +function D.SaveStorage() + -- ֻµ MAX_STORAGE_HISTORY ¼ + local aHistory = O.aHistory + if #aHistory > MAX_STORAGE_HISTORY then + local aStorageHistory = {} + for i = #aHistory - MAX_STORAGE_HISTORY + 1, #aHistory do + table.insert(aStorageHistory, aHistory[i]) + end + aHistory = aStorageHistory + end + X.SaveLUAData(STORAGE_FILE, { + bRecording = O.bRecording, + aHistory = aHistory, + }) +end + +-- ȡƵ +function D.GetChannelName(nChannel) + local szMsgType = X.CONSTANT.PLAYER_TALK_CHANNEL_TO_MSG_TYPE[nChannel] + return szMsgType and g_tStrings.tChannelName[szMsgType] or tostring(nChannel) +end + +-- ¼Ϣ (ⲿ) +-- szDirection: 'IN' վ, 'OUT' վ +function D.RecordMessage(szMsgID, nChannel, dwID, szName, bSelf, aMsg, oData, nSegCount, szDirection) + if not O.bRecording then + return + end + local szMsgUUID = aMsg and aMsg[1] and aMsg[1].u or '' + local nSegIndex = aMsg and aMsg[1] and aMsg[1].i or 0 + local szPart = aMsg and aMsg[2] or '' + local rec = { + szMsgID = szMsgID, + nChannel = nChannel, + dwID = dwID, + szName = szName, + bSelf = bSelf, + szMsgUUID = szMsgUUID, + nSegCount = nSegCount or 1, + nSegIndex = nSegIndex, + szPart = szPart, + oData = oData, + bComplete = oData ~= nil, + nTime = GetCurrentTime(), + szDirection = szDirection or 'IN', + szTarget = type(nChannel) == 'string' and nChannel or nil, + } + table.insert(O.aHistory, rec) + -- ¼ + while #O.aHistory > MAX_HISTORY do + table.remove(O.aHistory, 1) + end + -- ½ + D.RefreshList() +end + +-- ˢб +function D.RefreshList() + local frame = Station.Lookup('Normal/' .. FRAME_NAME) + if not frame then + return + end + local uiTable = X.UI(frame):Fetch('WndTable_History') + if not uiTable:Raw() then + return + end + local aDataSource = {} + for i, rec in ipairs(O.aHistory) do + local szPreview = '' + if rec.oData ~= nil then + szPreview = X.EncodeLUAData(rec.oData) + if #szPreview > 100 then + szPreview = szPreview:sub(1, 100) .. '...' + end + end + table.insert(aDataSource, { + nIndex = i, + szTime = X.FormatTime(rec.nTime, '%hh:%mm:%ss'), + szDirection = rec.szDirection or 'IN', + bComplete = rec.bComplete, + szChannel = D.GetChannelName(rec.nChannel), + szMsgID = rec.szMsgID, + szName = rec.szName, + szPreview = szPreview, + bSelf = rec.bSelf, + rec = rec, + }) + end + uiTable:DataSource(aDataSource) +end + +-- ʾ +function D.ShowDetail(rec) + if not rec then + return + end + local szDetailName = X.NSFormatString('{$NS}_BgMsgViewer_Detail') + if _G[szDetailName] and _G[szDetailName].Open then + _G[szDetailName].Open(rec) + end +end + +-- 򿪽 +function D.Open() + if D.IsOpened() then + D.Close() + return + end + local ui = X.UI.CreateFrame(FRAME_NAME, { + w = 1200, + h = 700, + text = X.PACKET_INFO.NAME .. g_tStrings.STR_CONNECT .. _L['BgMsgViewer'], + anchor = { s = 'CENTER', r = 'CENTER', x = 0, y = 0 }, + close = true, + esc = true, + resize = true, + minimize = true, + onSizeChange = function() + D.OnResize() + end, + }) + local nW, nH = ui:ContainerSize() + -- + local nX = 10 + ui:Append('WndCheckBox', { + name = 'WndCheckBox_Recording', + x = nX, y = 50, w = 'auto', + text = _L['Recording'], + checked = O.bRecording, + onCheck = function(bChecked) + O.bRecording = bChecked + D.SaveStorage() + D.UpdateEnableState() + end, + }) + nX = nX + 100 + ui:Append('WndButton', { + name = 'WndButton_Clear', + x = nX, y = 50, w = 80, h = 25, + text = _L['Clear'], + onClick = function() + O.aHistory = {} + D.RefreshList() + D.SaveStorage() + end, + }) + nX = nX + 90 + ui:Append('WndButton', { + name = 'WndButton_Segment', + x = nX, y = 50, w = 120, h = 25, + text = _L['Segment Viewer'], + onClick = function() + _G[X.NSFormatString('{$NS}_BgMsgSegmentViewer')].Open() + end, + }) + nX = nX + 130 + ui:Append('WndButton', { + name = 'WndButton_Sender', + x = nX, y = 50, w = 120, h = 25, + text = _L['BgMsg Sender'], + onClick = function() + _G[X.NSFormatString('{$NS}_BgMsgSender')].Open() + end, + }) + -- ťҶ룩 + ui:Append('WndButton', { + name = 'WndButton_Help', + x = nW - 30, y = 50, w = 20, h = 20, + buttonStyle = 'QUESTION', + tip = { + render = GetFormatText(_L['Blue: Outbound message'], 162, 128, 200, 255) .. GetFormatText('\n') + .. GetFormatText(_L['Green: Inbound message from self'], 162, 128, 255, 128) .. GetFormatText('\n') + .. GetFormatText(_L['Yellow: Incomplete message'], 162, 255, 255, 128) .. GetFormatText('\n') + .. GetFormatText(_L['White: Inbound message from others'], 162, 255, 255, 255), + rich = true, + position = X.UI.TIP_POSITION.TOP_BOTTOM, + }, + }) + -- + ui:Append('WndTable', { + name = 'WndTable_History', + x = 10, y = 85, + w = nW - 20, + h = nH - 95, + onRowLClick = function(rec, nIndex) + D.ShowDetail(rec.rec) + end, + onRowRClick = function(rec, nIndex) + if not rec or not rec.rec then + return + end + local r = rec.rec + local menu = { + { + szOption = _L['Replay'], + fnAction = function() + local szData = '' + if r.oData ~= nil then + szData = X.EncodeLUAData(r.oData, ' ') + end + -- ƵĿ + local nChannel = type(r.nChannel) == 'number' and r.nChannel or PLAYER_TALK_CHANNEL.WHISPER + local szTarget = r.szTarget or '' + -- ĿΪգ÷ΪĿ꣨ظ + if X.IsEmpty(szTarget) and nChannel == PLAYER_TALK_CHANNEL.WHISPER then + szTarget = r.szName or '' + end + -- ԭʼƵַĿҲΪĿ + if type(r.nChannel) == 'string' then + szTarget = r.nChannel + end + _G[X.NSFormatString('{$NS}_BgMsgSender')].Open({ + nChannel = nChannel, + szTarget = szTarget, + szMsgID = r.szMsgID or '', + szData = szData, + }) + end, + }, + { + szOption = _L['View Detail'], + fnAction = function() + D.ShowDetail(r) + end, + }, + } + PopupMenu(menu) + end, + columns = { + { + key = 'szTime', + title = _L['Time'], + alignHorizontal = 'center', + width = 80, + render = function(value, record) + local r, g, b = D.GetRecordColor(record) + return GetFormatText(value, 162, r, g, b) + end, + }, + { + key = 'szDirection', + title = _L['Dir'], + alignHorizontal = 'center', + width = 60, + render = function(value, record) + local r, g, b = D.GetRecordColor(record) + return GetFormatText(value, 162, r, g, b) + end, + }, + { + key = 'bComplete', + title = _L['Status'], + alignHorizontal = 'center', + width = 60, + render = function(value, record) + local r, g, b = D.GetRecordColor(record) + local szStatus = value and 'OK' or '..' + return GetFormatText(szStatus, 162, r, g, b) + end, + }, + { + key = 'szChannel', + title = _L['Channel'], + alignHorizontal = 'center', + width = 100, + render = function(value, record) + local r, g, b = D.GetRecordColor(record) + return GetFormatText(value, 162, r, g, b) + end, + }, + { + key = 'szName', + title = _L['Sender'], + alignHorizontal = 'left', + width = 120, + render = function(value, record) + local r, g, b = D.GetRecordColor(record) + return GetFormatText(' ' .. tostring(value), 162, r, g, b) + end, + }, + { + key = 'szMsgID', + title = _L['MsgID'], + alignHorizontal = 'left', + width = 200, + overflow = 'hidden', + render = function(value, record) + local r, g, b = D.GetRecordColor(record) + return GetFormatText(' ' .. tostring(value), 162, r, g, b) + end, + }, + { + key = 'szPreview', + title = _L['Preview'], + alignHorizontal = 'left', + minWidth = 200, + render = function(value, record) + local r, g, b = D.GetRecordColor(record) + return GetFormatText(' ' .. tostring(value), 162, r, g, b) + end, + }, + }, + dataSource = {}, + }) + D.RefreshList() + D.UpdateEnableState() +end + +-- ״̬ +function D.UpdateEnableState() + local frame = Station.Lookup('Normal/' .. FRAME_NAME) + if not frame then + return + end + local ui = X.UI(frame) + local bEnable = O.bRecording + ui:Fetch('WndButton_Clear'):Enable(bEnable) + ui:Fetch('WndButton_Segment'):Enable(bEnable) + ui:Fetch('WndButton_Sender'):Enable(bEnable) + ui:Fetch('WndTable_History'):Enable(bEnable) +end + +-- ȡ¼ɫ +function D.GetRecordColor(record) + if record.szDirection == 'OUT' then + return 128, 200, 255 + elseif record.bSelf then + return 128, 255, 128 + elseif not record.bComplete then + return 255, 255, 128 + end + return 255, 255, 255 +end + +function D.OnResize() + local frame = Station.Lookup('Normal/' .. FRAME_NAME) + if not frame then + return + end + local ui = X.UI(frame) + local nW, nH = ui:ContainerSize() + ui:Fetch('WndTable_History'):Size(nW - 20, nH - 95) + ui:Fetch('WndButton_Help'):Pos(nW - 30, 50) +end + +function D.Close() + X.UI.CloseFrame(FRAME_NAME) +end + +function D.IsOpened() + return Station.Lookup('Normal/' .. FRAME_NAME) ~= nil +end + +function D.IsRecording() + return O.bRecording +end + +-- ʼ +X.RegisterInit(function() + D.LoadStorage() +end) +X.RegisterFlush(function() + D.SaveStorage() +end) + +-------------------------------------------------------------------------------- +-- ȫֵ +-------------------------------------------------------------------------------- +do +local settings = { + name = FRAME_NAME, + exports = { + { + preset = 'UIEvent', + fields = { + 'Open', + 'Close', + 'IsOpened', + 'IsRecording', + 'RecordMessage', + }, + root = D, + }, + }, +} +_G[FRAME_NAME] = X.CreateModule(settings) +end + +--[[#DEBUG BEGIN]]X.ReportModuleLoading(MODULE_PATH, 'FINISH')--[[#DEBUG END]] diff --git a/MY_!Base/src/Dev_BgMsgViewer_Detail.lua b/MY_!Base/src/Dev_BgMsgViewer_Detail.lua new file mode 100644 index 0000000000..260551259a --- /dev/null +++ b/MY_!Base/src/Dev_BgMsgViewer_Detail.lua @@ -0,0 +1,210 @@ +-------------------------------------------------------------------------------- +-- This file is part of the JX3 Plugin Project. +-- @desc : ͨѶ鿴 +-- @copyright: Emil Zhai +-------------------------------------------------------------------------------- +---@class (partial) MY +local X = MY +-------------------------------------------------------------------------------- +local MODULE_PATH = X.NSFormatString('{$NS}_!Base/Dev_BgMsgViewer_Detail') +-------------------------------------------------------------------------------- +--[[#DEBUG BEGIN]]X.ReportModuleLoading(MODULE_PATH, 'START')--[[#DEBUG END]] +-------------------------------------------------------------------------------- +local _L = X.LoadLangPack(X.PACKET_INFO.FRAMEWORK_ROOT .. '/lang/Dev/') +-------------------------------------------------------------------------------- + +local FRAME_NAME = X.NSFormatString('{$NS}_BgMsgViewer_Detail') +local LABEL_WIDTH = 100 +local VALUE_WIDTH = 450 +local ROW_HEIGHT = 25 +local PADDING = 10 + +local O = {} +local D = {} + +-- ȡƵ +function D.GetChannelName(nChannel) + local szMsgType = X.CONSTANT.PLAYER_TALK_CHANNEL_TO_MSG_TYPE[nChannel] + return szMsgType and g_tStrings.tChannelName[szMsgType] or tostring(nChannel) +end + +-- ıڸƺTextEditor +function D.GetDetailText(rec) + local aLines = {} + table.insert(aLines, '========== BgMsg Detail ==========') + table.insert(aLines, 'Time: ' .. X.FormatTime(rec.nTime, '%yyyy-%MM-%dd %hh:%mm:%ss')) + table.insert(aLines, 'Direction: ' .. tostring(rec.szDirection or 'IN')) + table.insert(aLines, 'MsgID: ' .. tostring(rec.szMsgID)) + table.insert(aLines, 'MsgUUID: ' .. tostring(rec.szMsgUUID)) + table.insert(aLines, 'Channel: ' .. D.GetChannelName(rec.nChannel) .. ' (' .. tostring(rec.nChannel) .. ')') + if rec.szTarget then + table.insert(aLines, 'Target: ' .. tostring(rec.szTarget)) + end + table.insert(aLines, 'Sender: ' .. tostring(rec.szName) .. ' (' .. tostring(rec.dwID) .. ')') + table.insert(aLines, 'IsSelf: ' .. tostring(rec.bSelf)) + table.insert(aLines, 'SegCount: ' .. tostring(rec.nSegCount)) + table.insert(aLines, 'SegIndex: ' .. tostring(rec.nSegIndex)) + table.insert(aLines, 'Complete: ' .. tostring(rec.bComplete)) + table.insert(aLines, '') + table.insert(aLines, '---------- Raw Part ----------') + table.insert(aLines, tostring(rec.szPart)) + table.insert(aLines, '') + table.insert(aLines, '---------- Decoded Data ----------') + if rec.oData ~= nil then + table.insert(aLines, X.EncodeLUAData(rec.oData, ' ')) + else + table.insert(aLines, '(Not yet decoded or decode failed)') + end + return table.concat(aLines, '\n') +end + +-- ӱ +function D.AppendFormRow(ui, nY, szLabel, szValue) + ui:Append('Text', { + x = PADDING, y = nY, w = LABEL_WIDTH, h = ROW_HEIGHT, + text = szLabel, + font = 162, + alignHorizontal = 'right', + alignVertical = 'center', + }) + ui:Append('Text', { + x = PADDING + LABEL_WIDTH + 5, y = nY, w = VALUE_WIDTH, h = ROW_HEIGHT, + text = szValue, + font = 162, + alignHorizontal = 'left', + alignVertical = 'center', + }) + return nY + ROW_HEIGHT +end + +-- 򿪽 +function D.Open(rec) + if not rec then + return + end + -- رд + D.Close() + -- 浱ǰ¼ + O.rec = rec + -- + local ui = X.UI.CreateFrame(FRAME_NAME, { + w = 600, + h = 600, + text = X.PACKET_INFO.NAME .. g_tStrings.STR_CONNECT .. _L['BgMsgDetail'], + anchor = { s = 'CENTER', r = 'CENTER', x = 0, y = 0 }, + close = true, + esc = true, + resize = true, + minimize = false, + onSizeChange = function() + D.OnResize() + end, + onSettingsClick = function() + local menu = { + { + szOption = _L['Copy to clipboard'], + fnAction = function() + local szText = D.GetDetailText(O.rec) + SetDataToClip(szText) + X.OutputAnnounceMessage(_L['Detail has been copied to clipboard']) + end, + }, + { + szOption = _L['Open in TextEditor'], + fnAction = function() + X.UI.OpenTextEditor(D.GetDetailText(O.rec), { + title = 'BgMsg Detail - ' .. tostring(O.rec.szMsgID), + w = 600, + h = 500, + }) + end, + }, + } + PopupMenu(menu) + end, + }) + local nW, nH = ui:ContainerSize() + local nY = 50 + -- Ϣ + nY = D.AppendFormRow(ui, nY, _L['Time:'], X.FormatTime(rec.nTime, '%yyyy-%MM-%dd %hh:%mm:%ss')) + nY = D.AppendFormRow(ui, nY, _L['Direction:'], tostring(rec.szDirection or 'IN')) + nY = D.AppendFormRow(ui, nY, _L['MsgID:'], tostring(rec.szMsgID)) + nY = D.AppendFormRow(ui, nY, _L['MsgUUID:'], tostring(rec.szMsgUUID)) + nY = D.AppendFormRow(ui, nY, _L['Channel:'], D.GetChannelName(rec.nChannel) .. ' (' .. tostring(rec.nChannel) .. ')') + if rec.szTarget then + nY = D.AppendFormRow(ui, nY, _L['Target:'], tostring(rec.szTarget)) + end + nY = D.AppendFormRow(ui, nY, _L['Sender:'], tostring(rec.szName) .. ' (' .. tostring(rec.dwID) .. ')') + nY = D.AppendFormRow(ui, nY, _L['IsSelf:'], tostring(rec.bSelf)) + nY = D.AppendFormRow(ui, nY, _L['SegCount:'], tostring(rec.nSegCount)) + nY = D.AppendFormRow(ui, nY, _L['SegIndex:'], tostring(rec.nSegIndex)) + nY = D.AppendFormRow(ui, nY, _L['Complete:'], tostring(rec.bComplete)) + -- ָ + nY = nY + 10 + ui:Append('Text', { + x = PADDING, y = nY, w = nW - PADDING * 2, h = ROW_HEIGHT, + text = _L['Decoded Data:'], + font = 162, + alignHorizontal = 'center', + alignVertical = 'center', + }) + nY = nY + ROW_HEIGHT + -- Ԥ + local szData = '' + if rec.oData ~= nil then + szData = X.EncodeLUAData(rec.oData, ' ') + else + szData = _L['(Not yet decoded or decode failed)'] + end + O.nEditBoxY = nY -- EditBox Y λã OnResize + ui:Append('WndEditBox', { + name = 'WndEditBox_Data', + x = PADDING, y = nY, + w = nW - PADDING * 2, + h = nH - nY - PADDING, + multiline = true, + text = szData, + }) +end + +function D.OnResize() + local frame = Station.Lookup('Normal/' .. FRAME_NAME) + if not frame then + return + end + local ui = X.UI(frame) + local nW, nH = ui:ContainerSize() + ui:Fetch('WndEditBox_Data'):Size(nW - PADDING * 2, nH - O.nEditBoxY - PADDING) +end + +function D.Close() + X.UI.CloseFrame(FRAME_NAME) + O.rec = nil +end + +function D.IsOpened() + return Station.Lookup('Normal/' .. FRAME_NAME) ~= nil +end + +-------------------------------------------------------------------------------- +-- ȫֵ +-------------------------------------------------------------------------------- +do +local settings = { + name = FRAME_NAME, + exports = { + { + preset = 'UIEvent', + fields = { + 'Open', + 'Close', + 'IsOpened', + }, + root = D, + }, + }, +} +_G[FRAME_NAME] = X.CreateModule(settings) +end + +--[[#DEBUG BEGIN]]X.ReportModuleLoading(MODULE_PATH, 'FINISH')--[[#DEBUG END]] diff --git a/MY_!Base/src/PS.GlobalConfig.lua b/MY_!Base/src/PS.GlobalConfig.lua index 35c89ce570..53133bed11 100644 --- a/MY_!Base/src/PS.GlobalConfig.lua +++ b/MY_!Base/src/PS.GlobalConfig.lua @@ -205,25 +205,25 @@ function PS.OnPanelActive(wnd) nY = nY + 40 local uiMemory = ui:Append('Text', { - x = nX, y = nY, w = 150, + x = nX, y = nY, w = W - nX - nPaddingX, alpha = 150, font = 162, }) nY = nY + 25 local uiSize = ui:Append('Text', { - x = nX, y = nY, w = 150, + x = nX, y = nY, w = W - nX - nPaddingX, alpha = 150, font = 162, }) nY = nY + 25 local uiUIScale = ui:Append('Text', { - x = nX, y = nY, w = 150, + x = nX, y = nY, w = W - nX - nPaddingX, alpha = 150, font = 162, }) nY = nY + 25 local uiFontScale = ui:Append('Text', { - x = nX, y = nY, w = 150, + x = nX, y = nY, w = W - nX - nPaddingX, alpha = 150, font = 162, }) nY = nY + 25 diff --git a/MY_!Base/src/PS.Welcome.lua b/MY_!Base/src/PS.Welcome.lua index 3f0f642a99..2a80ab1418 100644 --- a/MY_!Base/src/PS.Welcome.lua +++ b/MY_!Base/src/PS.Welcome.lua @@ -255,56 +255,7 @@ function PS.OnPanelActive(wnd) x = x, h = 30, text = _L['Error message'], menu = function() - local menu = { - { - szOption = _L['Show error message'], - tip = { - render = _L['Show error message, please commit it while report bugs'], - position = X.UI.TIP_POSITION.BOTTOM_TOP, - }, - fnAction = function() - local szErrmsg = X.GetAddonErrorMessage() - local nErrmsgLen, nMaxLen = #szErrmsg, 1024 - if nErrmsgLen == 0 then - X.Alert(_L['No error message found.']) - return - end - if nErrmsgLen > 300 then - szErrmsg = szErrmsg:sub(0, nMaxLen) - .. '\n========================================' - .. '\n' .. '... ' .. (nErrmsgLen - nMaxLen) .. ' char(s) omitted.' - .. '\n========================================' - .. '\n# Full error logs:' - .. '\n> ' .. X.GetAbsolutePath(X.GetAddonErrorMessageFilePath()) - .. '\n========================================' - end - X.UI.OpenTextEditor(szErrmsg, { w = 800, h = 600, title = _L['Error message'] }) - X.UI.ClosePopupMenu() - end, - }, - { - szOption = _L['Open error message folder'], - fnAction = function() - X.OpenFolder(X.GetAbsolutePath(X.GetAddonErrorMessageFilePath())) - X.UI.ClosePopupMenu() - end, - }, - { - szOption = _L['Open logs folder'], - fnAction = function() - X.OpenFolder(X.GetAbsolutePath(X.FormatPath({'logs/', X.PATH_TYPE.ROLE}))) - X.UI.ClosePopupMenu() - end, - }, - X.CONSTANT.MENU_DIVIDER, - { - szOption = _L['Report bugs'], - fnAction = function() - X.OpenBrowser(X.PACKET_INFO.AUTHOR_FEEDBACK_URL) - X.UI.ClosePopupMenu() - end, - }, - } + local menu = {} if IsCtrlKeyDown() and IsAltKeyDown() and IsShiftKeyDown() then table.insert(menu, 1, { szOption = _L['Enable debug tools'], @@ -315,6 +266,7 @@ function PS.OnPanelActive(wnd) X.SetDebugging('Dev_UIManager', true) X.SetDebugging('Dev_UIFindStation', true) X.SetDebugging('Dev_DebugLogs', true) + X.SetDebugging('Dev_BgMsgViewer', true) X.OutputSystemAnnounceMessage(_L['Debug tools has been enabled...']) X.Panel.Reopen() X.UI.ClosePopupMenu() @@ -322,6 +274,65 @@ function PS.OnPanelActive(wnd) }) table.insert(menu, 2, X.CONSTANT.MENU_DIVIDER) end + if X.IsDebugging('Dev_BgMsgViewer') then + table.insert(menu, 1, { + szOption = _L['Open BgMsgViewer'], + rgb = { 128, 255, 128 }, + fnAction = function() + _G[X.NSFormatString('{$NS}_BgMsgViewer')].Open() + X.UI.ClosePopupMenu() + end, + }) + table.insert(menu, 2, X.CONSTANT.MENU_DIVIDER) + end + table.insert(menu, { + szOption = _L['Show error message'], + tip = { + render = _L['Show error message, please commit it while report bugs'], + position = X.UI.TIP_POSITION.BOTTOM_TOP, + }, + fnAction = function() + local szErrmsg = X.GetAddonErrorMessage() + local nErrmsgLen, nMaxLen = #szErrmsg, 1024 + if nErrmsgLen == 0 then + X.Alert(_L['No error message found.']) + return + end + if nErrmsgLen > 300 then + szErrmsg = szErrmsg:sub(0, nMaxLen) + .. '\n========================================' + .. '\n' .. '... ' .. (nErrmsgLen - nMaxLen) .. ' char(s) omitted.' + .. '\n========================================' + .. '\n# Full error logs:' + .. '\n> ' .. X.GetAbsolutePath(X.GetAddonErrorMessageFilePath()) + .. '\n========================================' + end + X.UI.OpenTextEditor(szErrmsg, { w = 800, h = 600, title = _L['Error message'] }) + X.UI.ClosePopupMenu() + end, + }) + table.insert(menu, { + szOption = _L['Open error message folder'], + fnAction = function() + X.OpenFolder(X.GetAbsolutePath(X.GetAddonErrorMessageFilePath())) + X.UI.ClosePopupMenu() + end, + }) + table.insert(menu, { + szOption = _L['Open logs folder'], + fnAction = function() + X.OpenFolder(X.GetAbsolutePath(X.FormatPath({'logs/', X.PATH_TYPE.ROLE}))) + X.UI.ClosePopupMenu() + end, + }) + table.insert(menu, X.CONSTANT.MENU_DIVIDER) + table.insert(menu, { + szOption = _L['Report bugs'], + fnAction = function() + X.OpenBrowser(X.PACKET_INFO.AUTHOR_FEEDBACK_URL) + X.UI.ClosePopupMenu() + end, + }) return menu end, }):AutoWidth():Width() + 5 diff --git a/MY_!Base/src/lib/Base.lua b/MY_!Base/src/lib/Base.lua index 02816f642a..ee0075d807 100644 --- a/MY_!Base/src/lib/Base.lua +++ b/MY_!Base/src/lib/Base.lua @@ -56,8 +56,8 @@ local IETF_BCP_47 = { } local _NAME_SPACE_ = 'MY' -local _BUILD_ = '20260121' -local _VERSION_ = '29.0.1' +local _BUILD_ = '20260127' +local _VERSION_ = '29.0.2' local _MENU_COLOR_ = {255, 165, 79} local _INTERFACE_ROOT_ = 'Interface/' local _ADDON_ROOT_ = _INTERFACE_ROOT_ .. _NAME_SPACE_ .. '/' diff --git a/MY_!Base/src/lib/Event.lua b/MY_!Base/src/lib/Event.lua index 10cfdb1997..4c4df78842 100644 --- a/MY_!Base/src/lib/Event.lua +++ b/MY_!Base/src/lib/Event.lua @@ -670,13 +670,17 @@ local BG_MSG_PROGRESS_EVENT = { szName = 'BgMsgProgress' } ------------------------------------ do local BG_MSG_PART = {} +local VIEWER_NAME = X.NSFormatString('{$NS}_BgMsgViewer') +local SEGMENT_VIEWER_NAME = X.NSFormatString('{$NS}_BgMsgSegmentViewer') local function OnBgMsg() local szMsgSID, nChannel, dwID, szName, aMsg, bSelf = arg0, arg1, arg2, arg3, arg4, arg2 == X.GetClientPlayerID() if not szMsgSID or szMsgSID:sub(1, #BG_MSG_ID_PREFIX) ~= BG_MSG_ID_PREFIX or szMsgSID:sub(-#BG_MSG_ID_SUFFIX) ~= BG_MSG_ID_SUFFIX then return end local szMsgID = szMsgSID:sub(#BG_MSG_ID_PREFIX + 1, -#BG_MSG_ID_SUFFIX - 1) - if not CommonEventRegister(BG_MSG_EVENT, szMsgID) then + local bRegistered = CommonEventRegister(BG_MSG_EVENT, szMsgID) + local bDebugging = X.IsDebugging('Dev_BgMsgViewer') + if not bRegistered and not bDebugging then return end -- pagination @@ -685,6 +689,10 @@ local function OnBgMsg() BG_MSG_PART[szMsgUUID] = {} end BG_MSG_PART[szMsgUUID][nSegIndex] = X.SimpleDecryptString(X.IsString(szPart) and szPart or '') + -- hook: record segment to segment viewer + if _G[SEGMENT_VIEWER_NAME] and _G[SEGMENT_VIEWER_NAME].RecordSegment then + _G[SEGMENT_VIEWER_NAME].RecordSegment(szMsgID, szMsgUUID, nChannel, dwID, szName, nSegCount, nSegIndex, szPart) + end -- fire progress event local nSegRecv = 0 for _, _ in pairs(BG_MSG_PART[szMsgUUID]) do @@ -696,7 +704,17 @@ local function OnBgMsg() local szPlain = table.concat(BG_MSG_PART[szMsgUUID]) local aData = szPlain and X.DecodeLUAData(szPlain) if aData then - CommonEventFirer(BG_MSG_EVENT, szMsgID, aData[1], nChannel, dwID, szName, bSelf) + -- hook: record complete message to viewer + if _G[VIEWER_NAME] and _G[VIEWER_NAME].RecordMessage then + _G[VIEWER_NAME].RecordMessage(szMsgID, nChannel, dwID, szName, bSelf, aMsg, aData[1], nSegCount) + end + -- hook: mark complete in segment viewer + if _G[SEGMENT_VIEWER_NAME] and _G[SEGMENT_VIEWER_NAME].MarkComplete then + _G[SEGMENT_VIEWER_NAME].MarkComplete(szMsgUUID) + end + if bRegistered then + CommonEventFirer(BG_MSG_EVENT, szMsgID, aData[1], nChannel, dwID, szName, bSelf) + end --[[#DEBUG BEGIN]] else X.OutputDebugMessage('BG_EVENT#' .. szMsgID, X.GetTraceback('Cannot decode BgMsg: ' .. szPlain), X.DEBUG_LEVEL.ERROR) @@ -729,6 +747,7 @@ end end do +local VIEWER_NAME = X.NSFormatString('{$NS}_BgMsgViewer') local MAX_CHANNEL_LEN = setmetatable({ [PLAYER_TALK_CHANNEL.RAID] = 300, [PLAYER_TALK_CHANNEL.BATTLE_FIELD] = 300, @@ -798,6 +817,11 @@ function X.SendBgMsg(nChannel, szMsgID, oData, bSilent) } me.Talk(nChannel, szTarget, aSay) end + -- hook: record outbound message to viewer + if _G[VIEWER_NAME] and _G[VIEWER_NAME].RecordMessage then + local aMsg = { { u = szMsgUUID, c = nSegCount, i = 1 }, szArg } + _G[VIEWER_NAME].RecordMessage(szMsgID, nChannel, me.dwID, me.szName, true, aMsg, oData, nSegCount, 'OUT') + end end end end diff --git a/MY_!Base/src/lib/UI.lua b/MY_!Base/src/lib/UI.lua index c2d7eb2cd3..d00ea2711d 100644 --- a/MY_!Base/src/lib/UI.lua +++ b/MY_!Base/src/lib/UI.lua @@ -2880,42 +2880,58 @@ local function SetComponentEnable(raw, bEnable) if bEnabled == bEnable then return end - -- make gray - local txt = GetComponentElement(raw, 'TEXT') - if txt then - local r, g, b = txt:GetFontColor() - local ratio = bEnable and 2.2 or (1 / 2.2) - if math.max(r, g, b) * ratio > 255 then - ratio = 255 / math.max(r, g, b) - end - txt:SetFontColor(math.ceil(r * ratio), math.ceil(g * ratio), math.ceil(b * ratio)) - end - -- make gray - local sha = GetComponentElement(raw, 'SHADOW') - if sha then - local r, g, b = sha:GetColorRGB() - local ratio = bEnable and 2.2 or (1 / 2.2) - if math.max(r, g, b) * ratio > 255 then - ratio = 255 / math.max(r, g, b) - end - sha:SetColorRGB(math.ceil(r * ratio), math.ceil(g * ratio), math.ceil(b * ratio)) - end - -- set sub elements enable - local combo = GetComponentElement(raw, 'COMBO_BOX') - if combo then - combo:Enable(bEnable) - end - local slider = GetComponentElement(raw, 'SLIDER') - if slider then - slider:Enable(bEnable) - end - local edit = GetComponentElement(raw, 'EDIT') - if edit then - edit:Enable(bEnable) - end - -- set enable - if raw.Enable then - raw:Enable(bEnable) + -- WndTable: set gray filter on header and content + if GetComponentType(raw) == 'WndTable' then + local hTotal = raw:Lookup('', '') + if hTotal then + hTotal:SetAlpha(bEnable and 255 or 128) + end + local scrollX = raw:Lookup('Scroll_X') + if scrollX then + scrollX:Enable(bEnable) + end + local scrollY = raw:Lookup('Scroll_Y') + if scrollY then + scrollY:Enable(bEnable) + end + else + -- make gray + local txt = GetComponentElement(raw, 'TEXT') + if txt then + local r, g, b = txt:GetFontColor() + local ratio = bEnable and 2.2 or (1 / 2.2) + if math.max(r, g, b) * ratio > 255 then + ratio = 255 / math.max(r, g, b) + end + txt:SetFontColor(math.ceil(r * ratio), math.ceil(g * ratio), math.ceil(b * ratio)) + end + -- make gray + local sha = GetComponentElement(raw, 'SHADOW') + if sha then + local r, g, b = sha:GetColorRGB() + local ratio = bEnable and 2.2 or (1 / 2.2) + if math.max(r, g, b) * ratio > 255 then + ratio = 255 / math.max(r, g, b) + end + sha:SetColorRGB(math.ceil(r * ratio), math.ceil(g * ratio), math.ceil(b * ratio)) + end + -- set sub elements enable + local combo = GetComponentElement(raw, 'COMBO_BOX') + if combo then + combo:Enable(bEnable) + end + local slider = GetComponentElement(raw, 'SLIDER') + if slider then + slider:Enable(bEnable) + end + local edit = GetComponentElement(raw, 'EDIT') + if edit then + edit:Enable(bEnable) + end + -- set enable + if raw.Enable then + raw:Enable(bEnable) + end end SetComponentProp(raw, 'bEnable', bEnable) end diff --git a/MY_Chat/src/MY_AutoHideChat.lua b/MY_Chat/src/MY_AutoHideChat.lua index 35c3de2158..eef186e4e1 100644 --- a/MY_Chat/src/MY_AutoHideChat.lua +++ b/MY_Chat/src/MY_AutoHideChat.lua @@ -14,7 +14,7 @@ local PLUGIN_ROOT = X.PACKET_INFO.ROOT .. PLUGIN_NAME local MODULE_NAME = 'MY_Chat' local _L = X.LoadLangPack(PLUGIN_ROOT .. '/lang/') -------------------------------------------------------------------------------- -if not X.AssertVersion(MODULE_NAME, _L[MODULE_NAME], '^29.0.0') then +if not X.AssertVersion(MODULE_NAME, _L[MODULE_NAME], '^29.0.2') then return end --[[#DEBUG BEGIN]]X.ReportModuleLoading(MODULE_PATH, 'START')--[[#DEBUG END]] diff --git a/MY_Chat/src/MY_Chat.lua b/MY_Chat/src/MY_Chat.lua index 22d71cd214..6e8faa9a4b 100644 --- a/MY_Chat/src/MY_Chat.lua +++ b/MY_Chat/src/MY_Chat.lua @@ -14,7 +14,7 @@ local PLUGIN_ROOT = X.PACKET_INFO.ROOT .. PLUGIN_NAME local MODULE_NAME = 'MY_ChatCopy' local _L = X.LoadLangPack(PLUGIN_ROOT .. '/lang/') -------------------------------------------------------------------------------- -if not X.AssertVersion(MODULE_NAME, _L[MODULE_NAME], '^29.0.0') then +if not X.AssertVersion(MODULE_NAME, _L[MODULE_NAME], '^29.0.2') then return end --[[#DEBUG BEGIN]]X.ReportModuleLoading(MODULE_PATH, 'START')--[[#DEBUG END]] diff --git a/MY_Chat/src/MY_ChatBlock.lua b/MY_Chat/src/MY_ChatBlock.lua index ff27c62376..0609382463 100644 --- a/MY_Chat/src/MY_ChatBlock.lua +++ b/MY_Chat/src/MY_ChatBlock.lua @@ -14,7 +14,7 @@ local PLUGIN_ROOT = X.PACKET_INFO.ROOT .. PLUGIN_NAME local MODULE_NAME = 'MY_ChatBlock' local _L = X.LoadLangPack(PLUGIN_ROOT .. '/lang/') -------------------------------------------------------------------------- -if not X.AssertVersion(MODULE_NAME, _L[MODULE_NAME], '^29.0.0') then +if not X.AssertVersion(MODULE_NAME, _L[MODULE_NAME], '^29.0.2') then return end --[[#DEBUG BEGIN]]X.ReportModuleLoading(MODULE_PATH, 'START')--[[#DEBUG END]] @@ -126,11 +126,9 @@ function D.OnTalkFilter(nChannel, t, dwTalkerID, szName, bEcho, bOnlyShowBallon, if #O.tBlockHistory[uuid].aRecent >= 10 then table.remove(O.tBlockHistory[uuid].aRecent, 1) end - local szType, r, g, b, nFont = X.CONSTANT.PLAYER_TALK_CHANNEL_TO_FONT[nChannel] - if szType then - nFont = GetMsgFont(szType) - r, g, b = GetMsgFontColor(nFont) - end + local szMsgType = TALK_CHANNEL_MSG_TYPE[nChannel] + local nFont = szMsgType and GetMsgFont(szMsgType) + local r, g, b = GetMsgFontColor(nFont, true) table.insert( O.tBlockHistory[uuid].aRecent, X.GetChatTimeXML(GetCurrentTime(), { @@ -516,8 +514,11 @@ function PS.OnPanelActive(wnd) end for _, v in ipairs(history.aRecent) do table.insert(aXml, v) + if not X.GetPureText(v):find('\n', 1, true) then + table.insert(aXml, X.CONSTANT.XML_LINE_BREAKER) + end end - X.OutputTip(X.UI(this):HoverItemRect(), table.concat(aXml, '\n'), true, ALW.BOTTOM_TOP) + X.OutputTip(X.UI(this):HoverItemRect(), table.concat(aXml, '\n'):gsub('\t', ' '), true, ALW.BOTTOM_TOP) end, function(id, text, data) HideTip() diff --git a/MY_Chat/src/MY_ChatCopy.lua b/MY_Chat/src/MY_ChatCopy.lua index febed02404..9f72986247 100644 --- a/MY_Chat/src/MY_ChatCopy.lua +++ b/MY_Chat/src/MY_ChatCopy.lua @@ -14,7 +14,7 @@ local PLUGIN_ROOT = X.PACKET_INFO.ROOT .. PLUGIN_NAME local MODULE_NAME = 'MY_ChatCopy' local _L = X.LoadLangPack(PLUGIN_ROOT .. '/lang/') -------------------------------------------------------------------------- -if not X.AssertVersion(MODULE_NAME, _L[MODULE_NAME], '^29.0.0') then +if not X.AssertVersion(MODULE_NAME, _L[MODULE_NAME], '^29.0.2') then return end --[[#DEBUG BEGIN]]X.ReportModuleLoading(MODULE_PATH, 'START')--[[#DEBUG END]] diff --git a/MY_Chat/src/MY_ChatEmotion.lua b/MY_Chat/src/MY_ChatEmotion.lua index 6f335a4e51..e0cbdfaf9b 100644 --- a/MY_Chat/src/MY_ChatEmotion.lua +++ b/MY_Chat/src/MY_ChatEmotion.lua @@ -14,7 +14,7 @@ local PLUGIN_ROOT = X.PACKET_INFO.ROOT .. PLUGIN_NAME local MODULE_NAME = 'MY_ChatEmotion' local _L = X.LoadLangPack(PLUGIN_ROOT .. '/lang/') -------------------------------------------------------------------------- -if not X.AssertVersion(MODULE_NAME, _L[MODULE_NAME], '^29.0.0') then +if not X.AssertVersion(MODULE_NAME, _L[MODULE_NAME], '^29.0.2') then return end --[[#DEBUG BEGIN]]X.ReportModuleLoading(MODULE_PATH, 'START')--[[#DEBUG END]] diff --git a/MY_Chat/src/MY_ChatFilter.lua b/MY_Chat/src/MY_ChatFilter.lua index 0fc43c341b..746f90a170 100644 --- a/MY_Chat/src/MY_ChatFilter.lua +++ b/MY_Chat/src/MY_ChatFilter.lua @@ -14,7 +14,7 @@ local PLUGIN_ROOT = X.PACKET_INFO.ROOT .. PLUGIN_NAME local MODULE_NAME = 'MY_ChatFilter' local _L = X.LoadLangPack(PLUGIN_ROOT .. '/lang/') -------------------------------------------------------------------------- -if not X.AssertVersion(MODULE_NAME, _L[MODULE_NAME], '^29.0.0') then +if not X.AssertVersion(MODULE_NAME, _L[MODULE_NAME], '^29.0.2') then return end --[[#DEBUG BEGIN]]X.ReportModuleLoading(MODULE_PATH, 'START')--[[#DEBUG END]] diff --git a/MY_Chat/src/MY_ChatMonitor.lua b/MY_Chat/src/MY_ChatMonitor.lua index 4a2e9ecdf6..8f7b896b8e 100644 --- a/MY_Chat/src/MY_ChatMonitor.lua +++ b/MY_Chat/src/MY_ChatMonitor.lua @@ -14,7 +14,7 @@ local PLUGIN_ROOT = X.PACKET_INFO.ROOT .. PLUGIN_NAME local MODULE_NAME = 'MY_ChatMonitor' local _L = X.LoadLangPack(PLUGIN_ROOT .. '/lang/') -------------------------------------------------------------------------- -if not X.AssertVersion(MODULE_NAME, _L[MODULE_NAME], '^29.0.0') then +if not X.AssertVersion(MODULE_NAME, _L[MODULE_NAME], '^29.0.2') then return end --[[#DEBUG BEGIN]]X.ReportModuleLoading(MODULE_PATH, 'START')--[[#DEBUG END]] diff --git a/MY_Chat/src/MY_ChatMosaics.lua b/MY_Chat/src/MY_ChatMosaics.lua index 327d34e970..0cf9d3b3b0 100644 --- a/MY_Chat/src/MY_ChatMosaics.lua +++ b/MY_Chat/src/MY_ChatMosaics.lua @@ -14,7 +14,7 @@ local PLUGIN_ROOT = X.PACKET_INFO.ROOT .. PLUGIN_NAME local MODULE_NAME = 'MY_ChatMosaics' local _L = X.LoadLangPack(PLUGIN_ROOT .. '/lang/') -------------------------------------------------------------------------- -if not X.AssertVersion(MODULE_NAME, _L[MODULE_NAME], '^29.0.0') then +if not X.AssertVersion(MODULE_NAME, _L[MODULE_NAME], '^29.0.2') then return end --[[#DEBUG BEGIN]]X.ReportModuleLoading(MODULE_PATH, 'START')--[[#DEBUG END]] diff --git a/MY_Chat/src/MY_ChatSwitch.lua b/MY_Chat/src/MY_ChatSwitch.lua index cabe2cf3bc..14cb2604a7 100644 --- a/MY_Chat/src/MY_ChatSwitch.lua +++ b/MY_Chat/src/MY_ChatSwitch.lua @@ -14,7 +14,7 @@ local PLUGIN_ROOT = X.PACKET_INFO.ROOT .. PLUGIN_NAME local MODULE_NAME = 'MY_ChatSwitch' local _L = X.LoadLangPack(PLUGIN_ROOT .. '/lang/') -------------------------------------------------------------------------- -if not X.AssertVersion(MODULE_NAME, _L[MODULE_NAME], '^29.0.0') then +if not X.AssertVersion(MODULE_NAME, _L[MODULE_NAME], '^29.0.2') then return end --[[#DEBUG BEGIN]]X.ReportModuleLoading(MODULE_PATH, 'START')--[[#DEBUG END]] diff --git a/MY_Chat/src/MY_TalkEx.lua b/MY_Chat/src/MY_TalkEx.lua index 63f5dcb5cf..70c352d590 100644 --- a/MY_Chat/src/MY_TalkEx.lua +++ b/MY_Chat/src/MY_TalkEx.lua @@ -14,7 +14,7 @@ local PLUGIN_ROOT = X.PACKET_INFO.ROOT .. PLUGIN_NAME local MODULE_NAME = 'MY_TalkEx' local _L = X.LoadLangPack(PLUGIN_ROOT .. '/lang/') -------------------------------------------------------------------------- -if not X.AssertVersion(MODULE_NAME, _L[MODULE_NAME], '^29.0.0') then +if not X.AssertVersion(MODULE_NAME, _L[MODULE_NAME], '^29.0.2') then return end --[[#DEBUG BEGIN]]X.ReportModuleLoading(MODULE_PATH, 'START')--[[#DEBUG END]] diff --git a/MY_Chat/src/MY_TeamBalloon.lua b/MY_Chat/src/MY_TeamBalloon.lua index baa8b72392..8b4c742f8e 100644 --- a/MY_Chat/src/MY_TeamBalloon.lua +++ b/MY_Chat/src/MY_TeamBalloon.lua @@ -14,7 +14,7 @@ local PLUGIN_ROOT = X.PACKET_INFO.ROOT .. PLUGIN_NAME local MODULE_NAME = 'MY_TeamBalloon' local _L = X.LoadLangPack(PLUGIN_ROOT .. '/lang/') -------------------------------------------------------------------------- -if not X.AssertVersion(MODULE_NAME, _L[MODULE_NAME], '^29.0.0') then +if not X.AssertVersion(MODULE_NAME, _L[MODULE_NAME], '^29.0.2') then return end --[[#DEBUG BEGIN]]X.ReportModuleLoading(MODULE_PATH, 'START')--[[#DEBUG END]] diff --git a/MY_Chat/src/MY_WhisperMention.lua b/MY_Chat/src/MY_WhisperMention.lua index d72d3d5045..2415dfdb89 100644 --- a/MY_Chat/src/MY_WhisperMention.lua +++ b/MY_Chat/src/MY_WhisperMention.lua @@ -14,7 +14,7 @@ local PLUGIN_ROOT = X.PACKET_INFO.ROOT .. PLUGIN_NAME local MODULE_NAME = 'MY_Chat' local _L = X.LoadLangPack(PLUGIN_ROOT .. '/lang/') -------------------------------------------------------------------------- -if not X.AssertVersion(MODULE_NAME, _L[MODULE_NAME], '^29.0.0') then +if not X.AssertVersion(MODULE_NAME, _L[MODULE_NAME], '^29.0.2') then return end --[[#DEBUG BEGIN]]X.ReportModuleLoading(MODULE_PATH, 'START')--[[#DEBUG END]] diff --git a/MY_Chat/src/PS.lua b/MY_Chat/src/PS.lua index 58aee19054..447de70659 100644 --- a/MY_Chat/src/PS.lua +++ b/MY_Chat/src/PS.lua @@ -14,7 +14,7 @@ local PLUGIN_ROOT = X.PACKET_INFO.ROOT .. PLUGIN_NAME local MODULE_NAME = 'MY_Chat' local _L = X.LoadLangPack(PLUGIN_ROOT .. '/lang/') -------------------------------------------------------------------------- -if not X.AssertVersion(MODULE_NAME, _L[MODULE_NAME], '^29.0.0') then +if not X.AssertVersion(MODULE_NAME, _L[MODULE_NAME], '^29.0.2') then return end --[[#DEBUG BEGIN]]X.ReportModuleLoading(MODULE_PATH, 'START')--[[#DEBUG END]] diff --git a/MY_Font/src/MY_Font.lua b/MY_Font/src/MY_Font.lua index 9d6dada04b..8059c06b5e 100644 --- a/MY_Font/src/MY_Font.lua +++ b/MY_Font/src/MY_Font.lua @@ -14,7 +14,7 @@ local PLUGIN_ROOT = X.PACKET_INFO.ROOT .. PLUGIN_NAME local MODULE_NAME = 'MY_Font' local _L = X.LoadLangPack(PLUGIN_ROOT .. '/lang/') -------------------------------------------------------------------------- -if not X.AssertVersion(MODULE_NAME, _L[MODULE_NAME], '^29.0.0') then +if not X.AssertVersion(MODULE_NAME, _L[MODULE_NAME], '^29.0.2') then return end --[[#DEBUG BEGIN]]X.ReportModuleLoading(MODULE_PATH, 'START')--[[#DEBUG END]] diff --git a/MY_FontResource/src/MY_FontResource.lua b/MY_FontResource/src/MY_FontResource.lua index 1ccba263d3..5808f640c6 100644 --- a/MY_FontResource/src/MY_FontResource.lua +++ b/MY_FontResource/src/MY_FontResource.lua @@ -14,7 +14,7 @@ local PLUGIN_ROOT = X.PACKET_INFO.ROOT .. PLUGIN_NAME local MODULE_NAME = 'MY_FontResource' local _L = X.LoadLangPack(PLUGIN_ROOT .. '/lang/') -------------------------------------------------------------------------- -if not X.AssertVersion(MODULE_NAME, _L[MODULE_NAME], '>=3.0.0') then +if not X.AssertVersion(MODULE_NAME, _L[MODULE_NAME], '^29.0.2') then return end --------------------------------------------------------------------------