yyl
2025-12-24 a38e02687f52e6d81e6fb6c1dcbf85ee76938325
Main/System/Chat/ChatManager.cs
@@ -11,10 +11,13 @@
    //<ChannelType,TalkData>
    public Dictionary<ChatChannel, List<TalkData>> talkDict = new Dictionary<ChatChannel, List<TalkData>>();
    //用于缓存玩家的外观信息
    public Dictionary<uint, TalkData> playerInfoDict = new Dictionary<uint, TalkData>();
    public Dictionary<int, ChatBubbleData> chatBubbles = new Dictionary<int, ChatBubbleData>();
    //<ChannelType,时间戳>
    public Dictionary<int, int> chatChannelSendTime = new Dictionary<int, int>();
    public event Action<ChatChannel, TalkData> OnUpdateTalkEvent;
    public event Action<ChatChannel, TalkData, bool> OnUpdateTalkEvent;
    public event Action OnUpdateTalkCacheListEvent;
    public Dictionary<int, int> chatChannelCD = new Dictionary<int, int>();
@@ -24,7 +27,6 @@
    public Color32 areaOtherColor;
    public Dictionary<int, int[]> chatChannelBulletColorArrDict = new Dictionary<int, int[]>();
    public Dictionary<ChatChannel, Color32> chatChannelBulletColorDict = new Dictionary<ChatChannel, Color32>();
    public int[] defaultChannelBulletColorArr;
    public Color32 defaultChannelBulletColor;
    public int characterLimit;
@@ -36,6 +38,7 @@
    public override void Init()
    {
        DTC0102_tagCDBPlayer.beforePlayerDataInitializeEvent += OnBeforePlayerDataInitializeEvent;
        DTC0102_tagCDBPlayer.beforePlayerDataInitializeEventOnRelogin += OnBeforePlayerDataInitializeEventOnRelogin;
        DTC0403_tagPlayerLoginLoadOK.playerLoginOkEvent += OnPlayerLoginOk;
        GuildManager.Instance.EnterOrQuitGuildEvent += EnterOrQuitGuildEvent;
@@ -44,45 +47,21 @@
        config = FuncConfigConfig.Get("TalkColor");
        areaMyColorArr = ConfigParse.GetMultipleStr<int>(config.Numerical1);
        areaMyColor = new Color32()
        {
            r = (byte)(areaMyColorArr.Length > 0 ? areaMyColorArr[0] : 0),
            g = (byte)(areaMyColorArr.Length > 1 ? areaMyColorArr[1] : 0),
            b = (byte)(areaMyColorArr.Length > 2 ? areaMyColorArr[2] : 0),
            a = (byte)(areaMyColorArr.Length > 3 ? areaMyColorArr[3] : 255),
        };
        areaMyColor = ParseColor32(areaMyColorArr);
        areaOtherColorArr = ConfigParse.GetMultipleStr<int>(config.Numerical2);
        areaOtherColor = new Color32()
        {
            r = (byte)(areaOtherColorArr.Length > 0 ? areaOtherColorArr[0] : 0),
            g = (byte)(areaOtherColorArr.Length > 1 ? areaOtherColorArr[1] : 0),
            b = (byte)(areaOtherColorArr.Length > 2 ? areaOtherColorArr[2] : 0),
            a = (byte)(areaOtherColorArr.Length > 3 ? areaOtherColorArr[3] : 255),
        };
        areaOtherColor = ParseColor32(areaOtherColorArr);
        chatChannelBulletColorArrDict = ConfigParse.ParseIntArrayDict(config.Numerical3);
        foreach (var kv in chatChannelBulletColorArrDict)
        {
            if (!IsValidChatChannel(kv.Key))
                continue;
            chatChannelBulletColorDict[(ChatChannel)kv.Key] = new Color32()
            {
                r = (byte)(kv.Value.Length > 0 ? kv.Value[0] : 0),
                g = (byte)(kv.Value.Length > 1 ? kv.Value[1] : 0),
                b = (byte)(kv.Value.Length > 2 ? kv.Value[2] : 0),
                a = (byte)(kv.Value.Length > 3 ? kv.Value[3] : 0),
            };
            chatChannelBulletColorDict[(ChatChannel)kv.Key] = ParseColor32(kv.Value);
        }
        defaultChannelBulletColorArr = ConfigParse.GetMultipleStr<int>(config.Numerical4);
        defaultChannelBulletColor = new Color32()
        {
            r = (byte)(defaultChannelBulletColorArr.Length > 0 ? defaultChannelBulletColorArr[0] : 0),
            g = (byte)(defaultChannelBulletColorArr.Length > 1 ? defaultChannelBulletColorArr[1] : 0),
            b = (byte)(defaultChannelBulletColorArr.Length > 2 ? defaultChannelBulletColorArr[2] : 0),
            a = (byte)(defaultChannelBulletColorArr.Length > 3 ? defaultChannelBulletColorArr[3] : 255),
        };
        defaultChannelBulletColor = ParseColor32(defaultChannelBulletColorArr);
        config = FuncConfigConfig.Get("TalkLimit");
        characterLimit = int.Parse(config.Numerical1);
@@ -90,38 +69,60 @@
        config = FuncConfigConfig.Get("TalkBubble");
        sysBubbleID = int.Parse(config.Numerical1);
        sysBubbleColorArr = ConfigParse.GetMultipleStr<int>(config.Numerical2);
        sysBubbleColor = new Color32()
        sysBubbleColor = ParseColor32(sysBubbleColorArr);
        ParseChatBubbleConfig();
    }
    public Color32 ParseColor32(int[] colorArr)
    {
        return new Color32()
        {
            r = (byte)(sysBubbleColorArr.Length > 0 ? sysBubbleColorArr[0] : 0),
            g = (byte)(sysBubbleColorArr.Length > 1 ? sysBubbleColorArr[1] : 0),
            b = (byte)(sysBubbleColorArr.Length > 2 ? sysBubbleColorArr[2] : 0),
            a = (byte)(sysBubbleColorArr.Length > 3 ? sysBubbleColorArr[3] : 255),
            r = (byte)(colorArr.Length > 0 ? colorArr[0] : 0),
            g = (byte)(colorArr.Length > 1 ? colorArr[1] : 0),
            b = (byte)(colorArr.Length > 2 ? colorArr[2] : 0),
            a = (byte)(colorArr.Length > 3 ? colorArr[3] : 255),
        };
    }
    public override void Release()
    {
        DTC0102_tagCDBPlayer.beforePlayerDataInitializeEvent -= OnBeforePlayerDataInitializeEvent;
        DTC0102_tagCDBPlayer.beforePlayerDataInitializeEventOnRelogin -= OnBeforePlayerDataInitializeEventOnRelogin;
        DTC0403_tagPlayerLoginLoadOK.playerLoginOkEvent -= OnPlayerLoginOk;
        GuildManager.Instance.EnterOrQuitGuildEvent -= EnterOrQuitGuildEvent;
    }
    //被踢出/退出工会时,切换聊天频道
    //被踢出/退出工会时,切换聊天频道,清理缓存的旧公会信息
    private void EnterOrQuitGuildEvent(bool obj)
    {
        if (!obj)
        {
            nowChatChannel = ChatChannel.World;
            nowChatTab = ChatTab.World;
            if (talkDict.ContainsKey(ChatChannel.Guild))
            {
                talkDict[ChatChannel.Guild].Clear();
            }
            if (lastTalkDataDict.ContainsKey(ChatChannel.Guild))
            {
                lastTalkDataDict.Remove(ChatChannel.Guild);
            }
        }
    }
    private void OnBeforePlayerDataInitializeEvent()
    {
        talkDict.Clear();
        ParseChatBubbleConfig();
        lastTalkDataDict.Clear();
        currentDay = -1;
        nowChatChannel = ChatChannel.World;
        nowChatTab = ChatTab.World;
    }
    private void OnBeforePlayerDataInitializeEventOnRelogin()
    {
        playerInfoDict.Clear();
    }
    private void OnPlayerLoginOk()
@@ -187,6 +188,11 @@
        return Encoding.UTF8.GetBytes(msg).Length;
    }
    public bool TryGetNewPlayerInfoByPlayerID(uint playerID, out TalkData talkData)
    {
        return playerInfoDict.TryGetValue(playerID, out talkData);
    }
    public bool TryGetBubble(int id, out ChatBubbleData bubble)
    {
        return chatBubbles.TryGetValue(id, out bubble);
@@ -218,20 +224,8 @@
                top = config.RightOffset.Length > 2 ? config.RightOffset[2] : 0,
                bottom = config.RightOffset.Length > 3 ? config.RightOffset[3] : 0,
            };
            bubble.myColor = new Color32()
            {
                r = (byte)(config.MyColor.Length > 0 ? config.MyColor[0] : 0),
                g = (byte)(config.MyColor.Length > 1 ? config.MyColor[1] : 0),
                b = (byte)(config.MyColor.Length > 2 ? config.MyColor[2] : 0),
                a = (byte)(config.MyColor.Length > 3 ? config.MyColor[3] : 255),
            };
            bubble.otherColor = new Color32()
            {
                r = (byte)(config.OtherColor.Length > 0 ? config.OtherColor[0] : 0),
                g = (byte)(config.OtherColor.Length > 1 ? config.OtherColor[1] : 0),
                b = (byte)(config.OtherColor.Length > 2 ? config.OtherColor[2] : 0),
                a = (byte)(config.OtherColor.Length > 3 ? config.OtherColor[3] : 255),
            };
            bubble.myColor = ParseColor32(config.MyColor);
            bubble.otherColor = ParseColor32(config.OtherColor);
            bubble.top = config.Top;
            chatBubbles.Add(config.ID, bubble);
        }
@@ -240,7 +234,7 @@
    {
        error = 0;
        int length = Encoding.Default.GetBytes(name).Length;
        int maxlength = characterLimit;  //纯中文字数
        int maxlength = characterLimit * 3;  //纯中文字数
        //var minlength = 3;
        if (length > maxlength)
        {
@@ -285,7 +279,7 @@
                break;
            case 1:
                // 长度过长
                SysNotifyMgr.Instance.ShowTip("NameError2", 7);
                SysNotifyMgr.Instance.ShowTip("NameError2", characterLimit);
                break;
            case 3:
                // 脏字
@@ -350,8 +344,36 @@
        OnDeleteTalkEvent?.Invoke(type);
    }
    public int currentDay = -1;
    public void AddTalkData(ChatChannel type, TalkData data)
    //记录各个频道最后一条聊天记录
    public Dictionary<ChatChannel, TalkData> lastTalkDataDict = new Dictionary<ChatChannel, TalkData>();
    public bool TryGetLastTalkData(out ChatChannel type, out TalkData data)
    {
        type = ChatChannel.World;
        data = null;
        bool isFound = false;
        foreach (var kvp in lastTalkDataDict)
        {
            ChatChannel channelType = kvp.Key;
            TalkData talkData = kvp.Value;
            bool isOpen = GetBulletSetting(channelType);
            if (!isOpen)
                continue;
            if (channelType == ChatChannel.Guild && !IsTabOpen(ChatTab.Guild, false))
                continue;
            if (data == null || talkData.TalkTime > data.TalkTime)
            {
                isFound = true;
                type = channelType;
                data = talkData;
            }
        }
        return isFound;
    }
    public void AddTalkData(ChatChannel type, TalkData data, bool isSendBullet)
    {
        //如果超过限制先删除旧数据
        TryDeleteTalkData(type);
@@ -360,10 +382,24 @@
            talkDict[type] = new List<TalkData>();
        }
        talkDict[type].Add(data);
        OnUpdateTalkEvent?.Invoke(type, data);
        if (!lastTalkDataDict.ContainsKey(type) || lastTalkDataDict[type].TalkTime <= data.TalkTime)
        {
            //展示的消息不能是日期行和系统行
            if (!data.isDate && !data.isSystem)
            {
                lastTalkDataDict[type] = data;
            }
        }
        if (isSendBullet)
        {
            OnUpdateTalkEvent?.Invoke(type, data, isSendBullet);
        }
    }
    public bool TryAddDate(int allSeconds, ChatChannel type)
    public int currentDay = -1;
    public bool TryAddDate(int allSeconds, ChatChannel type, bool isSendBullet)
    {
        DateTime talkTime = TimeUtility.GetTime((uint)allSeconds);
        if (talkTime.Day != currentDay)
@@ -375,17 +411,17 @@
                isDate = true,
                Content = Language.Get("Chat09", talkTime.Month, talkTime.Day),
                TalkTime = (uint)allSeconds,
            });
            }, isSendBullet);
            return true;
        }
        return false;
    }
    public void AddSysData(string msg, ArrayList infoList, ChatChannel type)
    public void AddSysData(string msg, ArrayList infoList, ChatChannel type, bool isSendBullet)
    {
        int allSeconds = TimeUtility.AllSeconds;
        // 如果隔天,增加日期行
        TryAddDate(allSeconds, type);
        TryAddDate(allSeconds, type, isSendBullet);
        if (!talkDict.ContainsKey(type))
        {
@@ -399,7 +435,7 @@
            BubbleBox = 1,
            TalkTime = (uint)allSeconds,
            InfoList = new ArrayList(infoList),
        });
        }, isSendBullet);
    }
    public void UpdateTalk(HB310_tagMCTalk vNetData)
@@ -415,7 +451,7 @@
        int allSeconds = TimeUtility.AllSeconds;
        // 如果隔天,增加日期行
        TryAddDate(allSeconds, type);
        TryAddDate(allSeconds, type, true);
        TalkData talkData = new TalkData()
        {
@@ -433,7 +469,9 @@
            ServerID = vNetData.ServerID,
            TalkTime = (uint)allSeconds,
        };
        AddTalkData(type, talkData);
        AddPlayerInfo(talkData);
        AddTalkData(type, talkData, true);
    }
    public void UpdateTalkCacheList(HB311_tagMCTalkCacheList vNetData)
@@ -453,13 +491,13 @@
        foreach (var info in vNetData.InfoList)
        {
            // 如果隔天,增加日期行
            TryAddDate((int)info.TalkTime, type);
            AddTalkData(type, new TalkData()
            TryAddDate((int)info.TalkTime, type, false);
            TalkData talkData = new TalkData()
            {
                ChannelType = vNetData.ChannelType,
                Name = info.Name,
                Name = UIHelper.ServerStringTrim(info.Name),
                PlayerID = info.PlayerID,
                Content = info.Content,
                Content = UIHelper.ServerStringTrim(info.Content),
                BubbleBox = info.BubbleBox,
                LV = info.LV,
                Job = info.Job,
@@ -469,9 +507,33 @@
                FacePic = info.FacePic,
                ServerID = info.ServerID,
                TalkTime = info.TalkTime,
            });
            };
            AddPlayerInfo(talkData);
            AddTalkData(type, talkData, false);
        }
        OnUpdateTalkCacheListEvent?.Invoke();
    }
    public event Action OnUpdatePlayerInfoEvent;
    public void AddPlayerInfo(TalkData data)
    {
        bool isChange = false;
        if (playerInfoDict.ContainsKey(data.PlayerID))
        {
            if (data.Name != playerInfoDict[data.PlayerID].Name ||
            data.BubbleBox != playerInfoDict[data.PlayerID].BubbleBox ||
            data.LV != playerInfoDict[data.PlayerID].LV ||
            data.Job != playerInfoDict[data.PlayerID].Job ||
            data.RealmLV != playerInfoDict[data.PlayerID].RealmLV ||
            data.TitleID != playerInfoDict[data.PlayerID].TitleID ||
            data.Face != playerInfoDict[data.PlayerID].Face ||
            data.FacePic != playerInfoDict[data.PlayerID].FacePic)
                isChange = true;
        }
        playerInfoDict[data.PlayerID] = data;
        if (isChange)
            OnUpdatePlayerInfoEvent?.Invoke();
    }
    #region 标签页
    // 当前展示的频道入口
@@ -534,19 +596,20 @@
    public string GetChatTabName(ChatTab chatTab)
    {
        return Language.Get(StringUtility.Contact("ChatTab", (int)chatTab));
        return Language.Get(StringUtility.Concat("ChatTab", ((int)chatTab).ToString()));
    }
    public string GetChatTabSelectIcon(ChatTab chatTab, bool isSelect)
    {
        return StringUtility.Contact(isSelect ? "ChatTabSelect" : "ChatTabUnSelect", (int)chatTab);
        return StringUtility.Concat(isSelect ? "ChatTabSelect" : "ChatTabUnSelect", ((int)chatTab).ToString());
    }
    #endregion
    #region 弹幕设置
    private Dictionary<ChatChannel, bool> bulletSettingDict = new Dictionary<ChatChannel, bool>();
    private string settingsKey { get { return StringUtility.Contact("BulletChatSettings_", PlayerDatas.Instance.PlayerId); } }
    private string settingsKey { get { return StringUtility.Concat("BulletChatSettings_", PlayerDatas.Instance.PlayerId.ToString()); } }
    // 设置特定频道的弹幕开关状态
    public void SetBulletSetting(ChatChannel channelType, bool isEnabled)
@@ -647,7 +710,6 @@
    public byte ChannelType;    // 0-世界;1-跨服;3- 仙盟   
    public bool isSystem = false;       //系统消息
    public bool isDate = false;          //分割日期
    public byte NameLen;
    public string Name;
    public uint PlayerID;
    public string Content;