| | |
| | | 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 |
| | | { |
| | | public override void Init() |
| | | { |
| | | ParseConfig(); |
| | | //var _uiframe = UIFrameMgr.Inst; |
| | | SpeechTranslate.Instance.translateResultEvent += TranslateResultEvent; |
| | | VoiceWarehouse.voiceRecoderEvent += VoiceRecoderEvent; |
| | | SDKUtility.Instance.onNetStatusChanged += 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; |
| | | } |
| | | |
| | | public override void UnInit() |
| | | { |
| | | |
| | | } |
| | | |
| | | bool serverInited = false; |
| | | |
| | | public int chatCharacterLimit { get; private set; } |
| | | public int bugleItem { get; private set; } |
| | | public List<ChatInfoType> chatChannels { get; private set; } |
| | | |
| | | public int chatInputLength { get; set; } |
| | | public StringBuilder m_EncodeBuilder = new StringBuilder(); |
| | | void ParseConfig() |
| | | { |
| | | chatCharacterLimit = int.Parse(ConfigManager.Instance.GetTemplate<FuncConfigConfig>("MessageLength").Numerical1); |
| | | var _funcCfg = ConfigManager.Instance.GetTemplate<FuncConfigConfig>("BugleItem"); |
| | | bugleItem = int.Parse(_funcCfg.Numerical1); |
| | | chatChannels = new List<ChatInfoType>(); |
| | | for (int i = (int)ChatInfoType.System; i <= (int)ChatInfoType.Friend; i++) |
| | | { |
| | | chatChannels.Add((ChatInfoType)i); |
| | | } |
| | | } |
| | | |
| | | public event Action<string, bool, bool> 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<ChatData> _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<RecentlyChat> recentlyChats = new List<RecentlyChat>(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; |
| | | netState = 0; |
| | | } |
| | | |
| | | public void OnSwitchAccount() |
| | | { |
| | | ClearAllVoice(); |
| | | } |
| | | |
| | | private void OnStageLoadFinish() |
| | | { |
| | | bool isDungeon = StageManager.Instance.CurrentStage is DungeonStage; |
| | | if (!isDungeon) |
| | | { |
| | | ClearAllVoice(); |
| | | } |
| | | } |
| | | |
| | | void ClearAllVoice() |
| | | { |
| | | speechDict.Clear(); |
| | | requestSpeechTime.Clear(); |
| | | } |
| | | |
| | | public class RecentlyChat |
| | | { |
| | | public string display = string.Empty; |
| | | public List<string> itemInfos = new List<string>(); |
| | | public List<int> itemIndexs = new List<int>(); |
| | | public List<string> itemNames = new List<string>(); |
| | | 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("<v=([0-9]+)_([0-9]+)>"); |
| | | private Dictionary<int, VoiceChat> m_VoiceChatDict = new Dictionary<int, VoiceChat>(); |
| | | |
| | | 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("<v=", _chat.tick, "_", _chat.length, ">", _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.secondworld.net.cn: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<string, string> dict = new Dictionary<string, string>(); |
| | | 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<HttpSpeech>(_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); |
| | | if (autoPlayVoices.Count > 0 |
| | | && autoPlayVoices[0].playerId == _player |
| | | && autoPlayVoices[0].tick == tick) |
| | | { |
| | | AutoPlayVoice(); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | DesignDebug.LogError(e.Message); |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | |
| | | private bool CheckRequestTimeLimit(int _playerId, long _tick) |
| | | { |
| | | AudioClip _clip = null; |
| | | if (TryGetSpeech(_playerId, _tick, out _clip)) |
| | | { |
| | | return false; |
| | | } |
| | | Dictionary<long, DateTime> dict = null; |
| | | if (!requestSpeechTime.TryGetValue(_playerId, out dict)) |
| | | { |
| | | dict = new Dictionary<long, DateTime>(); |
| | | 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<int, Dictionary<long, DateTime>> requestSpeechTime = new Dictionary<int, Dictionary<long, DateTime>>(); |
| | | |
| | | Dictionary<int, Dictionary<long, AudioClip>> speechDict = new Dictionary<int, Dictionary<long, AudioClip>>(); |
| | | public event Action<int, long> 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<long, AudioClip> dict = null; |
| | | if (!speechDict.TryGetValue(_decodec.playerId, out dict)) |
| | | { |
| | | dict = new Dictionary<long, AudioClip>(); |
| | | speechDict.Add(_decodec.playerId, dict); |
| | | } |
| | | 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); |
| | | } |
| | | if (speechDownloadSuccess != null) |
| | | { |
| | | speechDownloadSuccess(_decodec.playerId, _decodec.tick); |
| | | } |
| | | } |
| | | |
| | | public bool TryGetSpeech(int _playerId, long _tick, out AudioClip _clip) |
| | | { |
| | | Dictionary<long, AudioClip> _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; |
| | | } |
| | | |
| | | int netState = 0; |
| | | |
| | | private void OnNetStatusChanged(int _state) |
| | | { |
| | | netState = _state; |
| | | if (netState != 1 && netState != 4) |
| | | { |
| | | autoPlayVoices.Clear(); |
| | | } |
| | | } |
| | | |
| | | public bool voicePlaying { get; private set; } |
| | | public List<VoiceInfo> autoPlayVoices = new List<VoiceInfo>(); |
| | | |
| | | public void CheckAutoPlayVoice(ChatData _chat) |
| | | { |
| | | var _netState = netState; |
| | | #if UNITY_EDITOR |
| | | _netState = 1; |
| | | #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, _netState)) |
| | | { |
| | | 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<LoadingWin>() |
| | | || !(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, 4)) |
| | | { |
| | | RemoveAutoVoice(ChatInfoType.Fairy); |
| | | } |
| | | break; |
| | | case ChatBoolType.PrivatChatVoice4G: |
| | | case ChatBoolType.PrivateChatVoiceWifi: |
| | | if (!ChatSetting.Instance.GetAutoPlayVoice(ChatInfoType.Friend, 1) |
| | | && !ChatSetting.Instance.GetAutoPlayVoice(ChatInfoType.Friend, 4)) |
| | | { |
| | | RemoveAutoVoice(ChatInfoType.Friend); |
| | | } |
| | | break; |
| | | case ChatBoolType.TeamVoice4G: |
| | | case ChatBoolType.TeamVoiceWifi: |
| | | if (!ChatSetting.Instance.GetAutoPlayVoice(ChatInfoType.Team, 1) |
| | | && !ChatSetting.Instance.GetAutoPlayVoice(ChatInfoType.Team, 4)) |
| | | { |
| | | RemoveAutoVoice(ChatInfoType.Team); |
| | | } |
| | | break; |
| | | case ChatBoolType.WorldVoice4G: |
| | | case ChatBoolType.WorldVoiceWifi: |
| | | if (!ChatSetting.Instance.GetAutoPlayVoice(ChatInfoType.World, 1) |
| | | && !ChatSetting.Instance.GetAutoPlayVoice(ChatInfoType.World, 4)) |
| | | { |
| | | RemoveAutoVoice(ChatInfoType.World); |
| | | } |
| | | break; |
| | | case ChatBoolType.AreaVoiceWifi: |
| | | case ChatBoolType.AreaVoice4G: |
| | | if (!ChatSetting.Instance.GetAutoPlayVoice(ChatInfoType.Area, 1) |
| | | && !ChatSetting.Instance.GetAutoPlayVoice(ChatInfoType.Area, 4)) |
| | | { |
| | | 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(); |
| | | } |
| | | |
| | | private void CheckChatFloatOpen() |
| | | { |
| | | if (WindowCenter.Instance.ExitAnyFullScreenOrMaskWin() && !WindowCenter.Instance.CheckOpen<LoadingWin>() |
| | | && StageManager.Instance.CurrentStage is DungeonStage && !WindowCenter.Instance.CheckOpen<TreasureLevelUpWin>()) |
| | | { |
| | | if (!WindowCenter.Instance.CheckOpen<ChatFloatWin>()) |
| | | { |
| | | WindowCenter.Instance.Open<ChatFloatWin>(); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | if (WindowCenter.Instance.CheckOpen<ChatFloatWin>()) |
| | | { |
| | | WindowCenter.Instance.CloseImmediately<ChatFloatWin>(); |
| | | } |
| | | } |
| | | } |
| | | #endregion |
| | | |
| | | } |
| | | } |
| | | |
| | | 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
|
| | | {
|
| | | 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;
|
| | | }
|
| | |
|
| | | public override void UnInit()
|
| | | {
|
| | |
|
| | | }
|
| | |
|
| | | bool serverInited = false;
|
| | |
|
| | | public int chatCharacterLimit { get; private set; }
|
| | | public int bugleItem { get; private set; }
|
| | | public List<ChatInfoType> chatChannels { get; private set; }
|
| | |
|
| | | public int chatInputLength { get; set; }
|
| | | public StringBuilder m_EncodeBuilder = new StringBuilder();
|
| | | void ParseConfig()
|
| | | {
|
| | | chatCharacterLimit = int.Parse(Config.Instance.Get<FuncConfigConfig>("MessageLength").Numerical1);
|
| | | var _funcCfg = Config.Instance.Get<FuncConfigConfig>("BugleItem");
|
| | | bugleItem = int.Parse(_funcCfg.Numerical1);
|
| | | chatChannels = new List<ChatInfoType>();
|
| | | for (int i = (int)ChatInfoType.System; i <= (int)ChatInfoType.Friend; i++)
|
| | | {
|
| | | chatChannels.Add((ChatInfoType)i);
|
| | | }
|
| | | }
|
| | |
|
| | | public event Action<string, bool, bool> 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<ChatData> _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<RecentlyChat> recentlyChats = new List<RecentlyChat>(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;
|
| | | netState = 0;
|
| | | }
|
| | |
|
| | | public void OnSwitchAccount()
|
| | | {
|
| | | ClearAllVoice();
|
| | | }
|
| | |
|
| | | private void OnStageLoadFinish()
|
| | | {
|
| | | bool isDungeon = StageManager.Instance.CurrentStage is DungeonStage;
|
| | | if (!isDungeon)
|
| | | {
|
| | | ClearAllVoice();
|
| | | }
|
| | | }
|
| | |
|
| | | void ClearAllVoice()
|
| | | {
|
| | | speechDict.Clear();
|
| | | requestSpeechTime.Clear();
|
| | | }
|
| | |
|
| | | public class RecentlyChat
|
| | | {
|
| | | public string display = string.Empty;
|
| | | public List<string> itemInfos = new List<string>();
|
| | | public List<int> itemIndexs = new List<int>();
|
| | | public List<string> itemNames = new List<string>();
|
| | | 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("<v=([0-9]+)_([0-9]+)>");
|
| | | private Dictionary<int, VoiceChat> m_VoiceChatDict = new Dictionary<int, VoiceChat>();
|
| | |
|
| | | 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("<v=", _chat.tick, "_", _chat.length, ">", _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<string, string> dict = new Dictionary<string, string>();
|
| | | 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<HttpSpeech>(_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);
|
| | | if (autoPlayVoices.Count > 0
|
| | | && autoPlayVoices[0].playerId == _player
|
| | | && autoPlayVoices[0].tick == tick)
|
| | | {
|
| | | AutoPlayVoice();
|
| | | }
|
| | | }
|
| | | 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<long, DateTime> dict = null;
|
| | | if (!requestSpeechTime.TryGetValue(_playerId, out dict))
|
| | | {
|
| | | dict = new Dictionary<long, DateTime>();
|
| | | 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<int, Dictionary<long, DateTime>> requestSpeechTime = new Dictionary<int, Dictionary<long, DateTime>>();
|
| | |
|
| | | Dictionary<int, Dictionary<long, AudioClip>> speechDict = new Dictionary<int, Dictionary<long, AudioClip>>();
|
| | | public event Action<int, long> 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<long, AudioClip> dict = null;
|
| | | if (!speechDict.TryGetValue(_decodec.playerId, out dict))
|
| | | {
|
| | | dict = new Dictionary<long, AudioClip>();
|
| | | speechDict.Add(_decodec.playerId, dict);
|
| | | }
|
| | | 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);
|
| | | }
|
| | | if (speechDownloadSuccess != null)
|
| | | {
|
| | | speechDownloadSuccess(_decodec.playerId, _decodec.tick);
|
| | | }
|
| | | }
|
| | |
|
| | | public bool TryGetSpeech(int _playerId, long _tick, out AudioClip _clip)
|
| | | {
|
| | | Dictionary<long, AudioClip> _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;
|
| | | }
|
| | |
|
| | | int netState = 0;
|
| | |
|
| | | private void OnNetStatusChanged(NetworkReachability _state)
|
| | | {
|
| | | netState = (int)_state;
|
| | | if (netState != 1 && netState != 4)
|
| | | {
|
| | | autoPlayVoices.Clear();
|
| | | }
|
| | | }
|
| | |
|
| | | public bool voicePlaying { get; private set; }
|
| | | public List<VoiceInfo> autoPlayVoices = new List<VoiceInfo>();
|
| | |
|
| | | public void CheckAutoPlayVoice(ChatData _chat)
|
| | | {
|
| | | var _netState = netState;
|
| | | #if UNITY_EDITOR
|
| | | _netState = 1;
|
| | | #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, _netState))
|
| | | {
|
| | | 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<LoadingWin>()
|
| | | || !(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, 4))
|
| | | {
|
| | | RemoveAutoVoice(ChatInfoType.Fairy);
|
| | | }
|
| | | break;
|
| | | case ChatBoolType.PrivatChatVoice4G:
|
| | | case ChatBoolType.PrivateChatVoiceWifi:
|
| | | if (!ChatSetting.Instance.GetAutoPlayVoice(ChatInfoType.Friend, 1)
|
| | | && !ChatSetting.Instance.GetAutoPlayVoice(ChatInfoType.Friend, 4))
|
| | | {
|
| | | RemoveAutoVoice(ChatInfoType.Friend);
|
| | | }
|
| | | break;
|
| | | case ChatBoolType.TeamVoice4G:
|
| | | case ChatBoolType.TeamVoiceWifi:
|
| | | if (!ChatSetting.Instance.GetAutoPlayVoice(ChatInfoType.Team, 1)
|
| | | && !ChatSetting.Instance.GetAutoPlayVoice(ChatInfoType.Team, 4))
|
| | | {
|
| | | RemoveAutoVoice(ChatInfoType.Team);
|
| | | }
|
| | | break;
|
| | | case ChatBoolType.WorldVoice4G:
|
| | | case ChatBoolType.WorldVoiceWifi:
|
| | | if (!ChatSetting.Instance.GetAutoPlayVoice(ChatInfoType.World, 1)
|
| | | && !ChatSetting.Instance.GetAutoPlayVoice(ChatInfoType.World, 4))
|
| | | {
|
| | | RemoveAutoVoice(ChatInfoType.World);
|
| | | }
|
| | | break;
|
| | | case ChatBoolType.AreaVoiceWifi:
|
| | | case ChatBoolType.AreaVoice4G:
|
| | | if (!ChatSetting.Instance.GetAutoPlayVoice(ChatInfoType.Area, 1)
|
| | | && !ChatSetting.Instance.GetAutoPlayVoice(ChatInfoType.Area, 4))
|
| | | {
|
| | | 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();
|
| | | }
|
| | |
|
| | | private void CheckChatFloatOpen()
|
| | | {
|
| | | if (WindowCenter.Instance.ExitAnyFullScreenOrMaskWin() && !WindowCenter.Instance.CheckOpen<LoadingWin>()
|
| | | && StageManager.Instance.CurrentStage is DungeonStage && !WindowCenter.Instance.CheckOpen<TreasureLevelUpWin>())
|
| | | {
|
| | | if (!WindowCenter.Instance.CheckOpen<ChatFloatWin>())
|
| | | {
|
| | | WindowCenter.Instance.Open<ChatFloatWin>();
|
| | | }
|
| | | }
|
| | | else
|
| | | {
|
| | | if (WindowCenter.Instance.CheckOpen<ChatFloatWin>())
|
| | | {
|
| | | WindowCenter.Instance.CloseImmediately<ChatFloatWin>();
|
| | | }
|
| | | }
|
| | | }
|
| | | #endregion
|
| | |
|
| | | }
|
| | | }
|
| | |
|