using System; using System.Collections; using System.Collections.Generic; using System.Text; using System.Text.RegularExpressions; using TableConfig; using UnityEngine; namespace Snxxz.UI { public class ChatCenter : Model, IBeforePlayerDataInitialize, IPlayerLoginOk, ISwitchAccount { RealmModel realmModel { get { return ModelCenter.Instance.GetModel(); } } public override void Init() { ParseConfig(); //var _uiframe = UIFrameMgr.Inst; SpeechTranslate.Instance.translateResultEvent += TranslateResultEvent; VoiceWarehouse.voiceRecoderEvent += VoiceRecoderEvent; SDKUtility.Instance.OnNetworkStatusChanged += OnNetStatusChanged; ChatSetting.Instance.RefreshChatSetAct += RefreshChatSetAct; WindowCenter.Instance.windowAfterCloseEvent += WindowAfterCloseEvent; var httpRequest = VoiceHttpRequest.Instance; TimeMgr.Instance.OnSyntonyEvent += OnSyntonyEvent; VoiceHttpRequest.Instance.samplesDecodecComplete += SamplesDecodecComplete; WindowCenter.Instance.windowAfterOpenEvent += WindowAfterOpenEvent; StageManager.Instance.onStageLoadFinish += OnStageLoadFinish; PlayerRealmData.OnPlayerCollectEnd += OnPlayerCollectEnd; } public override void UnInit() { } bool serverInited = false; public int chatCharacterLimit { get; private set; } public int bugleItem { get; private set; } public List chatChannels { get; private set; } public int chatInputLength { get; set; } public StringBuilder m_EncodeBuilder = new StringBuilder(); void ParseConfig() { chatCharacterLimit = int.Parse(Config.Instance.Get("MessageLength").Numerical1); var _funcCfg = Config.Instance.Get("BugleItem"); bugleItem = int.Parse(_funcCfg.Numerical1); chatChannels = new List(); for (int i = (int)ChatInfoType.System; i <= (int)ChatInfoType.Friend; i++) { chatChannels.Add((ChatInfoType)i); } } public event Action UpdateChatValueEvent; public void ChangeChatValue(string _msg, bool _add, bool _force) { if (UpdateChatValueEvent != null) { UpdateChatValueEvent(_msg, _add, _force); } } public event Action UpdateChatType; public void ChangeChatType() { if (UpdateChatType != null) { UpdateChatType(); } } public event Action UpdateChatContent; public void UpdateChatContentPos() { if (UpdateChatContent != null) { UpdateChatContent(); } } public ChatData GetChatData(ChatInfoType _type, int _index, int _pteChatId = 0) { ChatData chat = null; if (_type == ChatInfoType.Friend) { var _list = ChatCtrl.Inst.GetChatInfo(_pteChatId == 0 ? ChatCtrl.Inst.PteChatID : _pteChatId); if (_list == null || _index >= _list.Count) { return null; } chat = _list[_index]; } else { List _list = ChatCtrl.Inst.GetChatInfo(_type); if (_list == null || _index >= _list.Count) { return null; } chat = _list[_index]; } return chat; } public const int RecentlyChatNum = 8; public List recentlyChats = new List(RecentlyChatNum); public event Action RecentlyChatChangeEvent; public RecentlyChat recentlyChat = null; public RecentlyChat SaveRecentlyChat(string _chat) { if (ChatCtrl.Inst.IsInviteChat(_chat) || Regex.IsMatch(_chat, ChatCtrl.KILL_IDENTIFY)) { return null; } if (s_VoiceRegex.IsMatch(_chat)) { _chat = s_VoiceRegex.Replace(_chat, string.Empty); } if (recentlyChats.FindIndex((x) => { return x.display.Equals(_chat); }) != -1) { return null; } if (recentlyChats.Count >= RecentlyChatNum) { var _old = recentlyChats[0]; recentlyChats.RemoveAt(0); _old = null; } var _recentlyChat = new RecentlyChat(_chat); recentlyChats.Add(_recentlyChat); if (RecentlyChatChangeEvent != null) { RecentlyChatChangeEvent(); } return _recentlyChat; } public void OnBeforePlayerDataInitialize() { recentlyChat = null; serverInited = false; m_VoiceChatDict.Clear(); autoPlayVoices.Clear(); voicePlaying = false; } public void OnSwitchAccount() { ClearAllVoice(); } private void OnStageLoadFinish() { bool isDungeon = StageManager.Instance.CurrentStage is DungeonStage; if (!isDungeon) { ClearAllVoice(); openChatAfterCollect = false; } if (PlayerDatas.Instance.baseData.MapID != 31230) { openChatAfterCollect = false; } } void ClearAllVoice() { speechDict.Clear(); requestSpeechTime.Clear(); } public class RecentlyChat { public string display = string.Empty; public List itemInfos = new List(); public List itemIndexs = new List(); public List itemNames = new List(); public RecentlyChat(string _chat) { display = _chat; } public void Add(string _name, string _itemInfo) { itemNames.Add(_name); itemInfos.Add(_itemInfo); } public void Reset() { itemIndexs.Clear(); for (int i = 0; i < itemInfos.Count; i++) { itemIndexs.Add(i); } } } #region 语音聊天 public static readonly Regex s_VoiceRegex = new Regex(""); private Dictionary m_VoiceChatDict = new Dictionary(); public class VoiceChat { public ChatInfoType chatType; public int index; public int toPlayer; public long tick; public byte length; public bool translate = false; public byte[] encode; public string result = string.Empty; } public void SetVoice(int _instance, ChatInfoType _type, float _length, int _toPlayer = 0) { if (!m_VoiceChatDict.ContainsKey(_instance)) { VoiceChat _chat = new VoiceChat() { chatType = _type, index = _instance, toPlayer = _toPlayer, tick = TimeUtility.ServerNow.Ticks, translate = false, encode = null, length = (byte)Mathf.Min((int)(_length * 10), 100), }; m_VoiceChatDict.Add(_instance, _chat); } } private void VoiceRecoderEvent(int _instance) { VoiceChat _chat; byte[] _encode; if (m_VoiceChatDict.TryGetValue(_instance, out _chat) && VoiceWarehouse.TryGetVoice(_instance, out _encode)) { if (_chat.translate) { m_VoiceChatDict.Remove(_instance); SendSpeech(_encode, _chat.tick); } else { _chat.encode = _encode; } } } private void TranslateResultEvent(int _instance, bool isOk, string _result) { VoiceChat _chat; if (m_VoiceChatDict.TryGetValue(_instance, out _chat)) { if (!isOk) { _result = string.Empty; } if (DirtyWordConfig.IsDirtWord(_result)) { _result = DirtyWordConfig.IsDirtWord(_result, '*'); } if (_chat.chatType != ChatInfoType.World && _chat.chatType != ChatInfoType.Area && _chat.chatType != ChatInfoType.Fairy && _chat.chatType != ChatInfoType.Friend && _chat.chatType != ChatInfoType.Team) { m_VoiceChatDict.Remove(_instance); return; } _chat.translate = true; _chat.result = _result; _result = StringUtility.Contact("", _chat.result); if (_chat.chatType == ChatInfoType.Friend) { if (_chat.toPlayer != 0) { ChatExtraData _info = ChatExtraData.Default; _info.infoint1 = _chat.toPlayer; ChatCtrl.Inst.SendChatInfo(_chat.chatType, _result, _info); } } else { ChatCtrl.Inst.SendChatInfo(_chat.chatType, _result); } if (null != _chat.encode) { SendSpeech(_chat.encode, _chat.tick); m_VoiceChatDict.Remove(_instance); } } } const string downloadUrl = "http://{0}.voice.2460web.com:53001/voice/download"; private void SendSpeech(byte[] encode, long _tick) { VoiceHttpRequest.Instance.Enqueue(encode, _tick, (int)PlayerDatas.Instance.PlayerId); } public void DownloadSpeech(int _playerId, long _tick) { Dictionary dict = new Dictionary(); dict.Add("voiceID", _tick.ToString()); dict.Add("playerID", _playerId.ToString()); dict.Add("appid", string.Empty); dict.Add("content", string.Empty); HttpRequest.Instance.RequestHttpPost(string.Format(downloadUrl, VersionConfig.Get().appId), dict, HttpRequest.defaultHttpContentType, 3, (bool isOk, string _result) => { if (isOk) { try { var speech = LitJson.JsonMapper.ToObject(_result); var tick = long.Parse(speech.voiceID); var _player = int.Parse(speech.playerID); if (string.IsNullOrEmpty(speech.content)) { if ((TimeUtility.ServerNow - TimeUtility.ClientOriginalTime.AddTicks(_tick)).TotalMinutes < 2)//可能是语音未上传成功 { AutoPlayVoice(); } else { if (autoPlayVoices.Count > 0 && autoPlayVoices[0].playerId == _player && autoPlayVoices[0].tick == tick) { RemoveAutoVoice(autoPlayVoices[0].playerId, autoPlayVoices[0].tick); AutoPlayVoice(); } else { SysNotifyMgr.Instance.ShowTip("VoiceOutTime"); } } return; } var bytes = Convert.FromBase64String(speech.content); SaveSpeech(_player, tick, bytes); } catch (Exception e) { DebugEx.LogError(e.Message); } } }); } private bool CheckRequestTimeLimit(int _playerId, long _tick) { AudioClip _clip = null; if (TryGetSpeech(_playerId, _tick, out _clip)) { return false; } Dictionary dict = null; if (!requestSpeechTime.TryGetValue(_playerId, out dict)) { dict = new Dictionary(); requestSpeechTime.Add(_playerId, dict); } if (dict.ContainsKey(_tick) && (DateTime.Now - dict[_tick]).TotalSeconds < 3.0f) { return true; } dict[_tick] = DateTime.Now; return false; } private Dictionary> requestSpeechTime = new Dictionary>(); Dictionary> speechDict = new Dictionary>(); public event Action speechDownloadSuccess; private void SaveSpeech(int _playerId, long _tick, byte[] encode) { VoiceCodec.Decode(encode, (float[] samples) => { VoiceHttpRequest.Instance.Enqueue(samples, _tick, _playerId); }); } private void SamplesDecodecComplete(VoiceHttpRequest.VoiceDecodec _decodec) { Dictionary dict = null; if (!speechDict.TryGetValue(_decodec.playerId, out dict)) { dict = new Dictionary(); speechDict.Add(_decodec.playerId, dict); } if (dict.ContainsKey(_decodec.tick)) { return; } var clip = AudioClip.Create("Sound", _decodec.samples.Length, 1, VoiceSettings.frequency, false); clip.SetData(_decodec.samples, 0); dict.Add(_decodec.tick, clip); if (_decodec.playerId == cachePlayerId && cacheTick == _decodec.tick) { PlaySpeech(clip, cacheLength); } else if (autoPlayVoices.Count > 0) { AutoPlayVoice(); } if (speechDownloadSuccess != null) { speechDownloadSuccess(_decodec.playerId, _decodec.tick); } } public bool TryGetSpeech(int _playerId, long _tick, out AudioClip _clip) { Dictionary _dict = null; if (speechDict.TryGetValue(_playerId, out _dict)) { if (_dict.ContainsKey(_tick)) { _clip = _dict[_tick]; return true; } } _clip = null; return false; } private int cachePlayerId = 0; private long cacheTick = 0; private float cacheLength = 0; public void PlaySpeech(int _playerId, long _tick, float _length) { if (CheckRequestTimeLimit(_playerId, _tick)) { return; } AudioClip _clip = null; if (TryGetSpeech(_playerId, _tick, out _clip)) { PlaySpeech(_clip, _length); cachePlayerId = 0; cacheTick = 0; cacheLength = 0; } else { cachePlayerId = _playerId; cacheTick = _tick; cacheLength = _length; DownloadSpeech(_playerId, _tick); } } public void PlaySpeech(AudioClip _clip, float _length) { SoundPlayer.Instance.mute = true; _length = Mathf.Max(1.0f, _length); voicePlaying = true; TimeMgr.Instance.Register(TimeMgr.SyntonyType.Audio, _length); SoundPlayer.Instance.PlayAudio(_clip); } private void OnSyntonyEvent(TimeMgr.SyntonyType _type) { if (_type == TimeMgr.SyntonyType.Audio) { SoundPlayer.Instance.mute = false; voicePlaying = false; AutoPlayVoice(); } } public struct HttpSpeech { public string voiceID; public string playerID; public string content; } byte GetPakChannelType(ChatInfoType _type) { switch (_type) { case ChatInfoType.World: return 1; case ChatInfoType.Area: return 5; case ChatInfoType.Team: return 4; case ChatInfoType.Fairy: return 2; case ChatInfoType.Friend: return 3; } return 1; } ChatInfoType GetPakChannelType(byte _type) { switch (_type) { case 5: return ChatInfoType.Area; case 1: return ChatInfoType.World; case 2: return ChatInfoType.Fairy; case 3: return ChatInfoType.Friend; case 4: return ChatInfoType.Team; } return ChatInfoType.World; } private void OnNetStatusChanged(NetworkReachability _state) { if ((int)SDKUtility.Instance.NetworkType == 0) { autoPlayVoices.Clear(); } } public bool voicePlaying { get; private set; } public List autoPlayVoices = new List(); public void CheckAutoPlayVoice(ChatData _chat) { var netType = (int)SDKUtility.Instance.NetworkType; #if UNITY_EDITOR netType = 2; #endif if (!serverInited) { return; } if (SystemSetting.Instance.GetSoundVolume() <= 0.01f) { return; } var _speechChat = _chat as ChatUeseData; if (null == _speechChat || !_speechChat.IsSound) { return; } if (_speechChat.player == PlayerDatas.Instance.PlayerId) { return; } if (!ChatSetting.Instance.GetAutoPlayVoice(_chat.type, netType)) { return; } if (autoPlayVoices.FindIndex((x) => { return x.playerId == _speechChat.player && x.tick == _speechChat.soundTick; }) != -1) { return; } SnxxzGame.Instance.StartCoroutine(Co_AutoPlay(new VoiceInfo() { playerId = _speechChat.player, tick = _speechChat.soundTick, type = _speechChat.type, length = _speechChat.soundLength, })); } private void WindowAfterCloseEvent(Window _win) { if (_win is LoadingWin) { AutoPlayVoice(); } CheckChatFloatOpen(); } IEnumerator Co_AutoPlay(VoiceInfo _info) { yield return WaitingForSecondConst.WaitMS500; if (serverInited) { autoPlayVoices.Add(_info); AutoPlayVoice(); } } private void AutoPlayVoice() { if (voicePlaying || WindowCenter.Instance.CheckOpen() || !(StageManager.Instance.CurrentStage is DungeonStage)) { return; } if (autoPlayVoices.Count > 0) { var _speech = autoPlayVoices[0]; AudioClip _clip; if (TryGetSpeech(_speech.playerId, _speech.tick, out _clip)) { PlaySpeech(_clip, _speech.length); autoPlayVoices.RemoveAt(0); } else { DownloadSpeech(_speech.playerId, _speech.tick); } } } private void RefreshChatSetAct(ChatBoolType _type, bool _open) { switch (_type) { case ChatBoolType.GradVoice4G: case ChatBoolType.GradVoiceWifi: if (!ChatSetting.Instance.GetAutoPlayVoice(ChatInfoType.Fairy, 1) && !ChatSetting.Instance.GetAutoPlayVoice(ChatInfoType.Fairy, 2)) { RemoveAutoVoice(ChatInfoType.Fairy); } break; case ChatBoolType.PrivatChatVoice4G: case ChatBoolType.PrivateChatVoiceWifi: if (!ChatSetting.Instance.GetAutoPlayVoice(ChatInfoType.Friend, 1) && !ChatSetting.Instance.GetAutoPlayVoice(ChatInfoType.Friend, 2)) { RemoveAutoVoice(ChatInfoType.Friend); } break; case ChatBoolType.TeamVoice4G: case ChatBoolType.TeamVoiceWifi: if (!ChatSetting.Instance.GetAutoPlayVoice(ChatInfoType.Team, 1) && !ChatSetting.Instance.GetAutoPlayVoice(ChatInfoType.Team, 2)) { RemoveAutoVoice(ChatInfoType.Team); } break; case ChatBoolType.WorldVoice4G: case ChatBoolType.WorldVoiceWifi: if (!ChatSetting.Instance.GetAutoPlayVoice(ChatInfoType.World, 1) && !ChatSetting.Instance.GetAutoPlayVoice(ChatInfoType.World, 2)) { RemoveAutoVoice(ChatInfoType.World); } break; case ChatBoolType.AreaVoiceWifi: case ChatBoolType.AreaVoice4G: if (!ChatSetting.Instance.GetAutoPlayVoice(ChatInfoType.Area, 1) && !ChatSetting.Instance.GetAutoPlayVoice(ChatInfoType.Area, 2)) { RemoveAutoVoice(ChatInfoType.Area); } break; } } private void RemoveAutoVoice(int _playerId, long _tick) { autoPlayVoices.RemoveAll((x) => { return x.playerId == _playerId && x.tick == _tick; }); } private void RemoveAutoVoice(ChatInfoType _type) { autoPlayVoices.RemoveAll((x) => { return x.type == _type; }); } public struct VoiceInfo { public int playerId; public long tick; public float length; public ChatInfoType type; } #endregion public void OnPlayerLoginOk() { serverInited = true; } #region 聊天浮动 private void WindowAfterOpenEvent(Window win) { CheckChatFloatOpen(); if (win is MainInterfaceWin) { CheckOpenChatAfterCollect(); } } private void CheckChatFloatOpen() { if (WindowCenter.Instance.ExitAnyFullScreenOrMaskWin() && !WindowCenter.Instance.CheckOpen() && StageManager.Instance.CurrentStage is DungeonStage && !WindowCenter.Instance.CheckOpen()) { if (!WindowCenter.Instance.CheckOpen()) { WindowCenter.Instance.Open(); } } else { if (WindowCenter.Instance.CheckOpen()) { WindowCenter.Instance.CloseImmediately(); } } } #endregion #region 仙盟宴会采集完后打开聊天界面 bool openChatAfterCollect = false; private void OnPlayerCollectEnd(int playerId, byte type) { if (playerId == PlayerDatas.Instance.baseData.PlayerID && type == 0 && PlayerDatas.Instance.baseData.MapID == 31230) { openChatAfterCollect = true; } CheckOpenChatAfterCollect(); } void CheckOpenChatAfterCollect() { if (!openChatAfterCollect) { return; } if (PlayerDatas.Instance.baseData.MapID != 31230) { return; } if (!WindowCenter.Instance.Open() || WindowCenter.Instance.ExitAnyFullScreenOrMaskWin() || StageManager.Instance.isLoading || NewBieCenter.Instance.inGuiding) { return; } openChatAfterCollect = false; if (!WindowCenter.Instance.CheckOpen()) { ChatCtrl.Inst.presentChatType = ChatInfoType.Fairy; WindowCenter.Instance.Open(); } } #endregion #region 境界渡劫私聊感谢 const string RealmThank = "ThankMessage"; const int RealmThankCount = 11; public void CheckSendRealmThanks() { try { var model = ModelCenter.Instance.GetModel(); var realmConfig = Config.Instance.Get(realmModel.cacheRealmLv); if (model.dungeonResult.leaderID == PlayerDatas.Instance.baseData.PlayerID && realmConfig != null && realmConfig.IsBigRealm == 1) { var count = 0; var configs = Config.Instance.GetAllValues(); for (int i = 0; i < configs.Count; i++) { if (configs[i].Lv < realmModel.cacheRealmLv && configs[i].IsBigRealm == 1) { count++; } else if (configs[i].Lv >= realmModel.cacheRealmLv) { break; } } if (count >= 3) { return; } var teamModel = ModelCenter.Instance.GetModel(); for (int i = 0; i < teamModel.myTeam.memberCount; i++) { Teammate teammate; if (teamModel.myTeam.TryGetMember(i, out teammate) && teammate.id != PlayerDatas.Instance.baseData.PlayerID && teammate.online) { ChatCtrl.Inst.PteChatID = (int)teammate.id; ChatCtrl.Inst.PteChatName = teammate.mateName; LanguageVerify.toPlayerLevel = teammate.level; var content = StringUtility.Contact(RealmThank, UnityEngine.Random.Range(1, RealmThankCount + 1)); ChatCtrl.Inst.SendChatInfo(ChatInfoType.Friend, Language.Get(content)); } } } } catch (Exception e) { DebugEx.Log(e.Message); } } #endregion } }