using System; using System.Collections.Generic; using System.Reflection; using System.Threading.Tasks; using BestHTTP.WebSocket; using Cysharp.Threading.Tasks; using Google.Protobuf; using Plugins.JNGame.Network.Entity; using Plugins.JNGame.Network.Util; using Plugins.JNGame.System; using Plugins.JNGame.Util; using UnityEngine; using Object = System.Object; namespace Plugins.JNGame.Network { public abstract class JNSocket : SystemBase { private WebSocket _socket; //消息Id int _id = 0; private UniTaskCompletionSource _onOpen; //创建通知 private EventDispatcher _event = new(); public override async Task OnInit() { await this.OnConnect(); } private async UniTask OnConnect() { var url = $"{await this.GetUrl()}"; this._socket = new WebSocket(new Uri(url)); this._socket.OnOpen += OnOpen; this._socket.OnMessage += OnMessageReceived; this._socket.OnError += OnError; this._socket.OnClosed += OnClosed; this._socket.OnBinary += Onbinary; NSystem.Log($"[JNSocket]初始化WebSocket成功,URL:{url}"); this._socket.Open(); //等待连接成功 await (this._onOpen = new UniTaskCompletionSource()).Task; } private void OnOpen(WebSocket websocket) { NSystem.Log($"[JNSocket] OnOpen"); this._onOpen.TrySetResult(); } private void OnMessageReceived(WebSocket websocket, string message) { NSystem.Log($"[JNSocket] OnMessageReceived"); } private void OnError(WebSocket websocket, Exception ex) { NSystem.Log($"[JNSocket] OnError"); } private void OnClosed(WebSocket websocket, ushort code, string message) { NSystem.Log($"[JNSocket] OnClosed"); } private void Onbinary(WebSocket websocket, byte[] data) { NSystem.Log($"[JNSocket] Onbinary"); Dispatch(NDataUtil.Parse(data)); } //通知消息 private void Dispatch(JNetParam data) { //发送消息 if(!_event.EventHandlers.ContainsKey($"{data.HId}")) return; List funs = _event.EventHandlers[$"{data.HId}"]; funs.ForEach(fun => { if(fun.Method.GetParameters().Length == 1 && typeof(IMessage).IsAssignableFrom(fun.Method.GetParameters()[0].ParameterType)) { var type = fun.Method.GetParameters()[0].ParameterType; var cType = type.GetProperty("Parser", BindingFlags.Static | BindingFlags.Public); if (cType != null) { var methodInfo = cType.PropertyType.GetMethod("ParseFrom",new[]{ typeof(byte[]) }); if (methodInfo != null) { var message = methodInfo.Invoke(cType.GetValue(null), new object[] { data.Bytes }); fun.Method.Invoke(fun.Target,new []{ message }); } } else { fun.Method.Invoke(fun.Target,new [] { (object)null }); } } else { fun.Method.Invoke(fun.Target,new object[]{ }); } }); } //外部监听消息 public void AddListener(int hId,Action listener) where T : IMessage { _event.AddListener($"{hId}",listener); } public void AddListener(int hId, global::System.Action listener) { _event.AddListener($"{hId}",listener); } //删除外部监听 public void RemoveListener(int hId,Action listener) where T : IMessage { _event.RemoveListener($"{hId}",listener); } protected abstract UniTask GetUrl(); //向服务器发送消息 public void Send(int hId,IMessage data = null) { _socket.Send(NDataUtil.Encrypt(JNetParam.Build(this._id++,hId).SetData(data))); } } }