using System; using UnityEngine; using BestHTTP.WebSocket; using Newtonsoft.Json; namespace JC.SocketIO { public class SocketIOClient : MonoBehaviour { private WebSocket _ws; private string _uri; public virtual void OnDestroy() { if (_ws != null) { _ws.Close(); _ws = null; } } public void connectServer(string uri) { this._uri = uri; this._ws = new WebSocket(new Uri(this._uri)); this._ws.StartPingThread = true; this._ws.OnOpen += delegate(WebSocket webSocket) { loadEntity(); }; this._ws.OnClosed = delegate(WebSocket webSocket, UInt16 code, string message) { destroyEntity(); }; this._ws.OnError = delegate(WebSocket webSocket, Exception ex) { destroyEntity(); }; this._ws.OnMessage = delegate(WebSocket webSocket, string message) { this.invoke(JsonConvert.DeserializeObject(message)); }; this._ws.Open(); } public void reconnectServer() { if (_ws != null) { _ws.Close(); _ws = null; } if (_uri != null) { connectServer(_uri); } } [NonSerialized] public bool isValid; [NonSerialized] public bool loaded; public virtual void onLoad() {} public virtual void onReload() {} public virtual void onDestroy() {} public virtual void onMiss() {} public void call(string func, params object[] args) { if (!isValid) return; DataPack dataPack = new DataPack(); dataPack.type = 1; dataPack.func = func; dataPack.args = Utility.FormatArgs(args); _ws.Send(JsonConvert.SerializeObject(dataPack)); } private void invoke(DataPack dataPack) { if (dataPack.type == 1) { System.Reflection.MethodInfo method = this.GetType().GetMethod(dataPack.func); Utility.FormatArgsType(dataPack.args, method.GetParameters()); method.Invoke(this, dataPack.args); } } public void loadEntity() { this.isValid = true; try { if (this.loaded) { this.onReload(); } else { this.onLoad(); } } catch (Exception e) { Debug.LogError(e.Message); } this.loaded = true; } private void destroyEntity() { try { if (this.isValid) { this.isValid = false; this.onDestroy(); } else { this.onMiss(); } } catch (Exception e) { Debug.LogError(e.Message); } } class DataPack { public int type; public string func; public object[] args; } class Utility { public static long GetTimestamp() { TimeSpan ts = DateTime.Now.ToUniversalTime() - new DateTime(1970, 1, 1); return (long)ts.TotalMilliseconds; } public static object[] FormatArgs(object[] args) { object[] newArgs = new object[args.Length]; for (int i = 0; i < args.Length; i++) { object arg = args[i]; if (!IsBaseType(arg.GetType())) { newArgs[i] = JsonConvert.SerializeObject(arg); } else { newArgs[i] = arg; } } return newArgs; } public static void FormatArgsType(object[] args, System.Reflection.ParameterInfo[] parameters) { int i = 0; foreach (var param in parameters) { Type type = param.ParameterType; if (IsBaseType(type)) { args[i] = Convert.ChangeType(args[i], type); } else { args[i] = JsonConvert.DeserializeObject((string) args[i], type); } i++; } } public static bool IsBaseType(Type type) { if (typeof(System.Int32).Equals(type)) return true; if (typeof(System.Int64).Equals(type)) return true; if (typeof(System.Single).Equals(type)) return true; if (typeof(System.Double).Equals(type)) return true; if (typeof(System.String).Equals(type)) return true; if (typeof(System.Boolean).Equals(type)) return true; return false; } } } }