少年修仙传客户端基础资源
lwb
2021-01-13 448feacbaaad6fed8cac0f16f72d24a241ba0b51
Assets/Plugins/PocoSDK/PocoManager.cs
@@ -14,306 +14,322 @@
public class PocoManager : MonoBehaviour
{
   public const int versionCode = 6;
   public int port = 5001;
   private bool mRunning;
   public AsyncTcpServer server = null;
   private RPCParser rpc = null;
   private SimpleProtocolFilter prot = null;
   private UnityDumper dumper = new UnityDumper();
   private ConcurrentDictionary<string, TcpClientState> inbox = new ConcurrentDictionary<string, TcpClientState>();
   private VRSupport vr_support = new VRSupport();
   private Dictionary<string, long> debugProfilingData = new Dictionary<string, long>() {
      { "dump", 0 },
      { "screenshot", 0 },
      { "handleRpcRequest", 0 },
      { "packRpcResponse", 0 },
      { "sendRpcResponse", 0 },
   };
    public const int versionCode = 6;
    public int port = 5001;
    private bool mRunning;
    public AsyncTcpServer server = null;
    private RPCParser rpc = null;
    private SimpleProtocolFilter prot = null;
    private UnityDumper dumper = new UnityDumper();
    private ConcurrentDictionary<string, TcpClientState> inbox = new ConcurrentDictionary<string, TcpClientState>();
    private VRSupport vr_support = new VRSupport();
    private Dictionary<string, long> debugProfilingData = new Dictionary<string, long>() {
        { "dump", 0 },
        { "screenshot", 0 },
        { "handleRpcRequest", 0 },
        { "packRpcResponse", 0 },
        { "sendRpcResponse", 0 },
    };
   class RPC : Attribute
   {
   }
    class RPC : Attribute
    {
    }
   void Awake()
   {
      Application.runInBackground = true;
      DontDestroyOnLoad(this);
      prot = new SimpleProtocolFilter();
      rpc = new RPCParser();
      rpc.addRpcMethod("isVRSupported", vr_support.isVRSupported);
      rpc.addRpcMethod("hasMovementFinished", vr_support.IsQueueEmpty);
      rpc.addRpcMethod("RotateObject", vr_support.RotateObject);
      rpc.addRpcMethod("ObjectLookAt", vr_support.ObjectLookAt);
      rpc.addRpcMethod("Screenshot", Screenshot);
      rpc.addRpcMethod("GetScreenSize", GetScreenSize);
      rpc.addRpcMethod("Dump", Dump);
      rpc.addRpcMethod("GetDebugProfilingData", GetDebugProfilingData);
      rpc.addRpcMethod("SetText", SetText);
    void Awake()
    {
        Application.runInBackground = true;
        DontDestroyOnLoad(this);
        prot = new SimpleProtocolFilter();
        rpc = new RPCParser();
        rpc.addRpcMethod("isVRSupported", vr_support.isVRSupported);
        rpc.addRpcMethod("hasMovementFinished", vr_support.IsQueueEmpty);
        rpc.addRpcMethod("RotateObject", vr_support.RotateObject);
        rpc.addRpcMethod("ObjectLookAt", vr_support.ObjectLookAt);
        rpc.addRpcMethod("Screenshot", Screenshot);
        rpc.addRpcMethod("GetScreenSize", GetScreenSize);
        rpc.addRpcMethod("Dump", Dump);
        rpc.addRpcMethod("GetDebugProfilingData", GetDebugProfilingData);
        rpc.addRpcMethod("SetText", SetText);
      rpc.addRpcMethod("GetSDKVersion", GetSDKVersion);
        rpc.addRpcMethod("GetSDKVersion", GetSDKVersion);
      mRunning = true;
        mRunning = true;
      for (int i = 0; i < 5; i++) {
         this.server = new AsyncTcpServer (port + i);
         this.server.Encoding = Encoding.UTF8;
         this.server.ClientConnected +=
            new EventHandler<TcpClientConnectedEventArgs> (server_ClientConnected);
         this.server.ClientDisconnected +=
            new EventHandler<TcpClientDisconnectedEventArgs> (server_ClientDisconnected);
         this.server.DatagramReceived +=
            new EventHandler<TcpDatagramReceivedEventArgs<byte[]>> (server_Received);
         try {
            this.server.Start ();
            Debug.Log (string.Format("Tcp server started and listening at {0}", server.Port));
            break;
         } catch (SocketException e) {
            // try next available port
            this.server = null;
         }
      }
      if (this.server == null) {
         Debug.LogError (string.Format("Unable to find an unused port from {0} to {1}", port, port + 5));
      }
      vr_support.ClearCommands();
   }
        for (int i = 0; i < 5; i++)
        {
            this.server = new AsyncTcpServer(port + i);
            this.server.Encoding = Encoding.UTF8;
            this.server.ClientConnected +=
                new EventHandler<TcpClientConnectedEventArgs>(server_ClientConnected);
            this.server.ClientDisconnected +=
                new EventHandler<TcpClientDisconnectedEventArgs>(server_ClientDisconnected);
            this.server.DatagramReceived +=
                new EventHandler<TcpDatagramReceivedEventArgs<byte[]>>(server_Received);
            try
            {
                this.server.Start();
                Debug.Log(string.Format("Tcp server started and listening at {0}", server.Port));
                break;
            }
            catch (SocketException e)
            {
                Debug.Log(string.Format("Tcp server bind to port {0} Failed!", server.Port));
                Debug.Log("--- Failed Trace Begin ---");
                Debug.LogError(e);
                Debug.Log("--- Failed Trace End ---");
                // try next available port
                this.server = null;
            }
        }
        if (this.server == null)
        {
            Debug.LogError(string.Format("Unable to find an unused port from {0} to {1}", port, port + 5));
        }
        vr_support.ClearCommands();
    }
   static void server_ClientConnected(object sender, TcpClientConnectedEventArgs e)
   {
      Debug.Log(string.Format("TCP client {0} has connected.",
         e.TcpClient.Client.RemoteEndPoint.ToString()));
   }
    static void server_ClientConnected(object sender, TcpClientConnectedEventArgs e)
    {
        Debug.Log(string.Format("TCP client {0} has connected.",
            e.TcpClient.Client.RemoteEndPoint.ToString()));
    }
   static void server_ClientDisconnected(object sender, TcpClientDisconnectedEventArgs e)
   {
      Debug.Log(string.Format("TCP client {0} has disconnected.",
         e.TcpClient.Client.RemoteEndPoint.ToString()));
   }
    static void server_ClientDisconnected(object sender, TcpClientDisconnectedEventArgs e)
    {
        Debug.Log(string.Format("TCP client {0} has disconnected.",
           e.TcpClient.Client.RemoteEndPoint.ToString()));
    }
   private void server_Received(object sender, TcpDatagramReceivedEventArgs<byte[]> e)
   {
      Debug.Log(string.Format("Client : {0} --> {1}",
         e.Client.TcpClient.Client.RemoteEndPoint.ToString(), e.Datagram.Length));
      TcpClientState internalClient = e.Client;
      string tcpClientKey = internalClient.TcpClient.Client.RemoteEndPoint.ToString();
      inbox.AddOrUpdate(tcpClientKey, internalClient, (n, o) =>
      {
         return internalClient;
      });
   }
    private void server_Received(object sender, TcpDatagramReceivedEventArgs<byte[]> e)
    {
        Debug.Log(string.Format("Client : {0} --> {1}",
            e.Client.TcpClient.Client.RemoteEndPoint.ToString(), e.Datagram.Length));
        TcpClientState internalClient = e.Client;
        string tcpClientKey = internalClient.TcpClient.Client.RemoteEndPoint.ToString();
        inbox.AddOrUpdate(tcpClientKey, internalClient, (n, o) =>
        {
            return internalClient;
        });
    }
   [RPC]
   private object Dump(List<object> param)
   {
      var onlyVisibleNode = true;
      if (param.Count > 0)
      {
         onlyVisibleNode = (bool)param[0];
      }
      var sw = new Stopwatch();
      sw.Start();
      var h = dumper.dumpHierarchy(onlyVisibleNode);
      debugProfilingData["dump"] = sw.ElapsedMilliseconds;
    [RPC]
    private object Dump(List<object> param)
    {
        var onlyVisibleNode = true;
        if (param.Count > 0)
        {
            onlyVisibleNode = (bool)param[0];
        }
        var sw = new Stopwatch();
        sw.Start();
        var h = dumper.dumpHierarchy(onlyVisibleNode);
        debugProfilingData["dump"] = sw.ElapsedMilliseconds;
      return h;
   }
        return h;
    }
   [RPC]
   private object Screenshot(List<object> param)
   {
      var sw = new Stopwatch();
      sw.Start();
    [RPC]
    private object Screenshot(List<object> param)
    {
        var sw = new Stopwatch();
        sw.Start();
      var tex = new Texture2D(Screen.width, Screen.height, TextureFormat.RGB24, false);
      tex.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0);
      tex.Apply(false);
      byte[] fileBytes = tex.EncodeToJPG(80);
      var b64img = Convert.ToBase64String(fileBytes);
      debugProfilingData["screenshot"] = sw.ElapsedMilliseconds;
      return new object[] { b64img, "jpg" };
   }
        var tex = new Texture2D(Screen.width, Screen.height, TextureFormat.RGB24, false);
        tex.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0);
        tex.Apply(false);
        byte[] fileBytes = tex.EncodeToJPG(80);
        var b64img = Convert.ToBase64String(fileBytes);
        debugProfilingData["screenshot"] = sw.ElapsedMilliseconds;
        return new object[] { b64img, "jpg" };
    }
   [RPC]
   private object GetScreenSize(List<object> param)
   {
      return new float[] { Screen.width, Screen.height };
   }
    [RPC]
    private object GetScreenSize(List<object> param)
    {
        return new float[] { Screen.width, Screen.height };
    }
   public void stopListening()
   {
      mRunning = false;
      server.Stop();
   }
    public void stopListening()
    {
        mRunning = false;
        server?.Stop();
    }
   [RPC]
   private object GetDebugProfilingData(List<object> param)
   {
      return debugProfilingData;
   }
    [RPC]
    private object GetDebugProfilingData(List<object> param)
    {
        return debugProfilingData;
    }
   [RPC]
   private object SetText(List<object> param)
   {
      var instanceId = Convert.ToInt32(param[0]);
      var textVal = param[1] as string;
      foreach (var go in GameObject.FindObjectsOfType<GameObject>())
      {
         if (go.GetInstanceID() == instanceId)
         {
            return UnityNode.SetText(go, textVal);
         }
      }
      return false;
   }
    [RPC]
    private object SetText(List<object> param)
    {
        var instanceId = Convert.ToInt32(param[0]);
        var textVal = param[1] as string;
        foreach (var go in GameObject.FindObjectsOfType<GameObject>())
        {
            if (go.GetInstanceID() == instanceId)
            {
                return UnityNode.SetText(go, textVal);
            }
        }
        return false;
    }
   [RPC]
   private object GetSDKVersion(List<object> param)
   {
      return versionCode;
   }
    [RPC]
    private object GetSDKVersion(List<object> param)
    {
        return versionCode;
    }
   void Update()
   {
      foreach (TcpClientState client in inbox.Values)
      {
         List<string> msgs = client.Prot.swap_msgs();
         msgs.ForEach(delegate (string msg)
         {
            var sw = new Stopwatch();
            sw.Start();
            var t0 = sw.ElapsedMilliseconds;
            string response = rpc.HandleMessage(msg);
            var t1 = sw.ElapsedMilliseconds;
            byte[] bytes = prot.pack(response);
            var t2 = sw.ElapsedMilliseconds;
            server.Send(client.TcpClient, bytes);
            var t3 = sw.ElapsedMilliseconds;
            debugProfilingData["handleRpcRequest"] = t1 - t0;
            debugProfilingData["packRpcResponse"] = t2 - t1;
            TcpClientState internalClientToBeThrowAway;
            string tcpClientKey = client.TcpClient.Client.RemoteEndPoint.ToString();
            inbox.TryRemove(tcpClientKey, out internalClientToBeThrowAway);
         });
      }
    void Update()
    {
        foreach (TcpClientState client in inbox.Values)
        {
            List<string> msgs = client.Prot.swap_msgs();
            msgs.ForEach(delegate (string msg)
            {
                var sw = new Stopwatch();
                sw.Start();
                var t0 = sw.ElapsedMilliseconds;
                string response = rpc.HandleMessage(msg);
                var t1 = sw.ElapsedMilliseconds;
                byte[] bytes = prot.pack(response);
                var t2 = sw.ElapsedMilliseconds;
                server.Send(client.TcpClient, bytes);
                var t3 = sw.ElapsedMilliseconds;
                debugProfilingData["handleRpcRequest"] = t1 - t0;
                debugProfilingData["packRpcResponse"] = t2 - t1;
                TcpClientState internalClientToBeThrowAway;
                string tcpClientKey = client.TcpClient.Client.RemoteEndPoint.ToString();
                inbox.TryRemove(tcpClientKey, out internalClientToBeThrowAway);
            });
        }
      vr_support.PeekCommand();
   }
        vr_support.PeekCommand();
    }
   void OnApplicationQuit()
   {
       // stop listening thread
      stopListening();
   }
    void OnApplicationQuit()
    {
        // stop listening thread
        stopListening();
    }
    void OnDestroy()
    {
        // stop listening thread
        stopListening();
    }
}
public class RPCParser
{
   public delegate object RpcMethod(List<object> param);
    public delegate object RpcMethod(List<object> param);
   protected Dictionary<string, RpcMethod> RPCHandler = new Dictionary<string, RpcMethod>();
   private JsonSerializerSettings settings = new JsonSerializerSettings()
   {
      StringEscapeHandling = StringEscapeHandling.EscapeNonAscii
   };
    protected Dictionary<string, RpcMethod> RPCHandler = new Dictionary<string, RpcMethod>();
    private JsonSerializerSettings settings = new JsonSerializerSettings()
    {
        StringEscapeHandling = StringEscapeHandling.EscapeNonAscii
    };
   public string HandleMessage(string json)
   {
      Dictionary<string, object> data = JsonConvert.DeserializeObject<Dictionary<string, object>>(json, settings);
      if (data.ContainsKey("method"))
      {
         string method = data["method"].ToString();
         List<object> param = null;
         if (data.ContainsKey("params"))
         {
            param = ((JArray)(data["params"])).ToObject<List<object>>();
         }
    public string HandleMessage(string json)
    {
        Dictionary<string, object> data = JsonConvert.DeserializeObject<Dictionary<string, object>>(json, settings);
        if (data.ContainsKey("method"))
        {
            string method = data["method"].ToString();
            List<object> param = null;
            if (data.ContainsKey("params"))
            {
                param = ((JArray)(data["params"])).ToObject<List<object>>();
            }
         object idAction = null;
         if (data.ContainsKey("id"))
         {
            // if it have id, it is a request
            idAction = data["id"];
         }
            object idAction = null;
            if (data.ContainsKey("id"))
            {
                // if it have id, it is a request
                idAction = data["id"];
            }
         string response = null;
         object result = null;
         try
         {
            result = RPCHandler[method](param);
         }
         catch (Exception e)
         {
            // return error response
            Debug.Log(e);
            response = formatResponseError(idAction, null, e);
            return response;
         }
            string response = null;
            object result = null;
            try
            {
                result = RPCHandler[method](param);
            }
            catch (Exception e)
            {
                // return error response
                Debug.Log(e);
                response = formatResponseError(idAction, null, e);
                return response;
            }
         // return result response
         response = formatResponse(idAction, result);
         return response;
            // return result response
            response = formatResponse(idAction, result);
            return response;
      }
      else
      {
         // do not handle response
         Debug.Log("ignore message without method");
         return null;
      }
   }
        }
        else
        {
            // do not handle response
            Debug.Log("ignore message without method");
            return null;
        }
    }
   // Call a method in the server
   public string formatRequest(string method, object idAction, List<object> param = null)
   {
      Dictionary<string, object> data = new Dictionary<string, object>();
      data["jsonrpc"] = "2.0";
      data["method"] = method;
      if (param != null)
      {
         data["params"] = JsonConvert.SerializeObject(param, settings);
      }
      // if idAction is null, it is a notification
      if (idAction != null)
      {
         data["id"] = idAction;
      }
      return JsonConvert.SerializeObject(data, settings);
   }
    // Call a method in the server
    public string formatRequest(string method, object idAction, List<object> param = null)
    {
        Dictionary<string, object> data = new Dictionary<string, object>();
        data["jsonrpc"] = "2.0";
        data["method"] = method;
        if (param != null)
        {
            data["params"] = JsonConvert.SerializeObject(param, settings);
        }
        // if idAction is null, it is a notification
        if (idAction != null)
        {
            data["id"] = idAction;
        }
        return JsonConvert.SerializeObject(data, settings);
    }
   // Send a response from a request the server made to this client
   public string formatResponse(object idAction, object result)
   {
      Dictionary<string, object> rpc = new Dictionary<string, object>();
      rpc["jsonrpc"] = "2.0";
      rpc["id"] = idAction;
      rpc["result"] = result;
      return JsonConvert.SerializeObject(rpc, settings);
   }
    // Send a response from a request the server made to this client
    public string formatResponse(object idAction, object result)
    {
        Dictionary<string, object> rpc = new Dictionary<string, object>();
        rpc["jsonrpc"] = "2.0";
        rpc["id"] = idAction;
        rpc["result"] = result;
        return JsonConvert.SerializeObject(rpc, settings);
    }
   // Send a error to the server from a request it made to this client
   public string formatResponseError(object idAction, IDictionary<string, object> data, Exception e)
   {
      Dictionary<string, object> rpc = new Dictionary<string, object>();
      rpc["jsonrpc"] = "2.0";
      rpc["id"] = idAction;
    // Send a error to the server from a request it made to this client
    public string formatResponseError(object idAction, IDictionary<string, object> data, Exception e)
    {
        Dictionary<string, object> rpc = new Dictionary<string, object>();
        rpc["jsonrpc"] = "2.0";
        rpc["id"] = idAction;
      Dictionary<string, object> errorDefinition = new Dictionary<string, object>();
      errorDefinition["code"] = 1;
      errorDefinition["message"] = e.ToString();
        Dictionary<string, object> errorDefinition = new Dictionary<string, object>();
        errorDefinition["code"] = 1;
        errorDefinition["message"] = e.ToString();
      if (data != null)
      {
         errorDefinition["data"] = data;
      }
        if (data != null)
        {
            errorDefinition["data"] = data;
        }
      rpc["error"] = errorDefinition;
      return JsonConvert.SerializeObject(rpc, settings);
   }
        rpc["error"] = errorDefinition;
        return JsonConvert.SerializeObject(rpc, settings);
    }
   public void addRpcMethod(string name, RpcMethod method)
   {
      RPCHandler[name] = method;
   }
    public void addRpcMethod(string name, RpcMethod method)
    {
        RPCHandler[name] = method;
    }
}