76 【常规】聊天系统-客户端
1.新增玩家外观缓存机制,当聊天中的其他玩家更换外观时(名字,头像,头像框,称号时),统一该玩家所有聊天的外观表现为最新的
2.修复断线重连后聊天内容布局错位问题
3.修复断线重连后自动发送了错误弹幕问题
| | |
| | | |
| | | //<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>(); |
| | |
| | | private void OnBeforePlayerDataInitializeEvent() |
| | | { |
| | | talkDict.Clear(); |
| | | playerInfoDict.Clear(); |
| | | currentDay = -1; |
| | | ParseChatBubbleConfig(); |
| | | nowChatChannel = ChatChannel.World; |
| | | nowChatTab = ChatTab.World; |
| | |
| | | public static int GetUTF8InfoLen(string msg) |
| | | { |
| | | 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) |
| | |
| | | } |
| | | |
| | | public int currentDay = -1; |
| | | public void AddTalkData(ChatChannel type, TalkData data) |
| | | public void AddTalkData(ChatChannel type, TalkData data, bool isSend) |
| | | { |
| | | //如果超过限制先删除旧数据 |
| | | TryDeleteTalkData(type); |
| | |
| | | talkDict[type] = new List<TalkData>(); |
| | | } |
| | | talkDict[type].Add(data); |
| | | if (isSend) |
| | | { |
| | | OnUpdateTalkEvent?.Invoke(type, data); |
| | | } |
| | | } |
| | | |
| | | public bool TryAddDate(int allSeconds, ChatChannel type) |
| | | public bool TryAddDate(int allSeconds, ChatChannel type, bool isSend) |
| | | { |
| | | DateTime talkTime = TimeUtility.GetTime((uint)allSeconds); |
| | | if (talkTime.Day != currentDay) |
| | |
| | | isDate = true, |
| | | Content = Language.Get("Chat09", talkTime.Month, talkTime.Day), |
| | | TalkTime = (uint)allSeconds, |
| | | }); |
| | | }, isSend); |
| | | return true; |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | public void AddSysData(string msg, ArrayList infoList, ChatChannel type) |
| | | public void AddSysData(string msg, ArrayList infoList, ChatChannel type, bool isSend) |
| | | { |
| | | int allSeconds = TimeUtility.AllSeconds; |
| | | // 如果隔天,增加日期行 |
| | | TryAddDate(allSeconds, type); |
| | | TryAddDate(allSeconds, type, isSend); |
| | | |
| | | if (!talkDict.ContainsKey(type)) |
| | | { |
| | |
| | | BubbleBox = 1, |
| | | TalkTime = (uint)allSeconds, |
| | | InfoList = new ArrayList(infoList), |
| | | }); |
| | | }, isSend); |
| | | } |
| | | |
| | | public void UpdateTalk(HB310_tagMCTalk vNetData) |
| | |
| | | |
| | | int allSeconds = TimeUtility.AllSeconds; |
| | | // 如果隔天,增加日期行 |
| | | TryAddDate(allSeconds, type); |
| | | TryAddDate(allSeconds, type, true); |
| | | |
| | | TalkData talkData = new TalkData() |
| | | { |
| | |
| | | ServerID = vNetData.ServerID, |
| | | TalkTime = (uint)allSeconds, |
| | | }; |
| | | AddTalkData(type, talkData); |
| | | AddPlayerInfo(talkData); |
| | | AddTalkData(type, talkData, true); |
| | | |
| | | } |
| | | |
| | | public void UpdateTalkCacheList(HB311_tagMCTalkCacheList vNetData) |
| | |
| | | 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, |
| | |
| | | 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 标签页 |
| | | // 当前展示的频道入口 |
| | |
| | | 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; |
| | |
| | | ChatManager manager { get { return ChatManager.Instance; } } |
| | | public void Refresh(CellView cell) |
| | | { |
| | | if (!manager.TryGetChatData(ChatManager.Instance.nowChatChannel, cell.index, out TalkData data)) |
| | | if (!manager.TryGetChatData(ChatManager.Instance.nowChatChannel, cell.index, out TalkData nowData) || nowData == null) |
| | | return; |
| | | avatarCell.InitUI(AvatarHelper.GetAvatarModel((int)data.PlayerID, (int)data.Face, (int)data.PlayerID, data.Job)); |
| | | |
| | | m_ChatBubble.DisplayContent(nowData.Content, true); |
| | | |
| | | bool hasNewPlayerInfo = manager.TryGetNewPlayerInfoByPlayerID(nowData.PlayerID, out TalkData newPlayerInfo); |
| | | TalkData data = hasNewPlayerInfo ? newPlayerInfo : nowData; |
| | | |
| | | avatarCell.InitUI(AvatarHelper.GetAvatarModel((int)data.PlayerID, (int)data.Face, (int)data.FacePic, data.Job)); |
| | | avatarCell.button.SetListener(() => |
| | | { |
| | | |
| | | }); |
| | | title.InitUI(data.RealmLV, (int)data.TitleID); |
| | | |
| | | |
| | | |
| | | m_ChatBubble.DisplayContent(data.Content, true); |
| | | |
| | | int bubbleID = ChatBubbleHelper.GetOtherChatBubbleID(data.Job, (int)data.BubbleBox); |
| | | m_ChatBubble.DisplayBubble(bubbleID, (int)data.PlayerID); |
| | | |
| | |
| | | protected override void OnPreOpen() |
| | | { |
| | | base.OnPreOpen(); |
| | | DTC0102_tagCDBPlayer.beforePlayerDataInitializeEvent += OnBeforePlayerDataInitializeEvent; |
| | | manager.OnChatTabChangeEvent += OnChatTabChange; |
| | | manager.OnUpdateTalkEvent += OnUpdateTalkEvent; |
| | | manager.OnUpdateTalkCacheListEvent += OnUpdateTalkCacheList; |
| | | manager.OnDeleteTalkEvent += OnDeleteTalkEvent; |
| | | manager.OnUpdatePlayerInfoEvent += OnUpdatePlayerInfoEvent; |
| | | |
| | | scrChatTab.OnRefreshCell += OnRefreshChatTabCell; |
| | | scrWorld.OnGetDynamicSize += OnGetWorldChatDynamicSize; |
| | |
| | | protected override void OnPreClose() |
| | | { |
| | | base.OnPreClose(); |
| | | DTC0102_tagCDBPlayer.beforePlayerDataInitializeEvent -= OnBeforePlayerDataInitializeEvent; |
| | | manager.OnChatTabChangeEvent -= OnChatTabChange; |
| | | manager.OnUpdateTalkEvent -= OnUpdateTalkEvent; |
| | | manager.OnUpdateTalkCacheListEvent -= OnUpdateTalkCacheList; |
| | | manager.OnDeleteTalkEvent -= OnDeleteTalkEvent; |
| | | manager.OnUpdatePlayerInfoEvent -= OnUpdatePlayerInfoEvent; |
| | | |
| | | scrChatTab.OnRefreshCell -= OnRefreshChatTabCell; |
| | | scrWorld.OnGetDynamicSize -= OnGetWorldChatDynamicSize; |
| | |
| | | scrGuild.mScrollRect.onValueChanged.RemoveListener(OnGuildScrollValChange); |
| | | GlobalTimeEvent.Instance.secondEvent -= OnSecondEvent; |
| | | clickScreenOtherSpace.RemoveAllListeners(); |
| | | } |
| | | |
| | | private void OnBeforePlayerDataInitializeEvent() |
| | | { |
| | | CreaterAll(manager.nowChatTab); |
| | | } |
| | | |
| | | private void OnUpdatePlayerInfoEvent() |
| | | { |
| | | RefreshAll(manager.nowChatChannel, isUpdatePlayerInfo: true); |
| | | } |
| | | |
| | | private void OnDeleteTalkEvent(ChatChannel channel) |
| | |
| | | return 0; |
| | | } |
| | | |
| | | private void RefreshAll(ChatChannel type, uint playerId = 0) |
| | | private void RefreshAll(ChatChannel type, uint playerId = 0, bool isUpdatePlayerInfo = false) |
| | | { |
| | | scrChatTab.m_Scorller.RefreshActiveCellViews(); |
| | | if (type == ChatChannel.World) |
| | | { |
| | | RefreshChat(type, scrWorld, playerId); |
| | | RefreshChat(type, scrWorld, playerId, isUpdatePlayerInfo); |
| | | } |
| | | else if (type == ChatChannel.Guild) |
| | | { |
| | | RefreshChat(type, scrGuild, playerId); |
| | | RefreshChat(type, scrGuild, playerId, isUpdatePlayerInfo); |
| | | } |
| | | |
| | | } |
| | | |
| | | private void RefreshChat(ChatChannel type, ScrollerController scroller, uint playerId = 0) |
| | | private void RefreshChat(ChatChannel type, ScrollerController scroller, uint playerId = 0, bool isUpdatePlayerInfo = false) |
| | | { |
| | | if (!manager.TryGetTalkData(type, out List<TalkData> datas) || datas == null) |
| | | return; |
| | |
| | | float height = GetHeight(talkDataType, data.Content, data.InfoList); |
| | | scroller.m_Scorller.AddHeight(true, height); |
| | | //Debug.Log($"ChatWin AddCell i {i} AddHeight {height}"); |
| | | |
| | | } |
| | | if (isUpdatePlayerInfo) |
| | | { |
| | | scroller.m_Scorller.RefreshActiveCellViews(); |
| | | } |
| | | } |
| | | else |
| | |
| | | ServerTipDetails.ShowMarquee(msg, tipInfoList, order); |
| | | break; |
| | | case SysNotifyType.ChatChannelWorld: |
| | | ChatManager.Instance.AddSysData(msg, tipInfoList, ChatChannel.World); |
| | | ChatManager.Instance.AddSysData(msg, tipInfoList, ChatChannel.World, true); |
| | | break; |
| | | case SysNotifyType.ChatChannelGuild: |
| | | ChatManager.Instance.AddSysData(msg, tipInfoList, ChatChannel.Guild); |
| | | ChatManager.Instance.AddSysData(msg, tipInfoList, ChatChannel.Guild, true); |
| | | break; |
| | | case SysNotifyType.SysRealmTip: |
| | | if (OnSysTipEvent != null) |