├── README.md ├── pomelo-unityclient.sln ├── pomelo-unityclient.userprefs └── pomelo-unityclient ├── bin └── Debug │ ├── SimpleJson.dll │ ├── SocketIO.dll │ ├── SuperSocket.ClientEngine.Common.dll │ ├── SuperSocket.ClientEngine.Core.dll │ ├── SuperSocket.ClientEngine.Protocol.dll │ ├── SuperSocket.ClientEngine.Proxy.dll │ ├── WebSocket4Net.dll │ ├── pomelo-unityclient.dll │ └── pomelo-unityclient.pdb ├── pomelo-unityclient.csproj ├── pomelo-unityclient.pidb └── pomelo-unityclient ├── EventManager.cs ├── PomeloClient.cs └── Protocol.cs /README.md: -------------------------------------------------------------------------------- 1 | pomelo-unityclient 2 | ============================= 3 | This is the pomelo client for unity3d. The project is based on some libraries as follows: 4 | 5 | * WebSocket4Net (http://websocket4net.codeplex.com/), and you should choose the .Net 3.5 runtime version. 6 | 7 | * UnitySocketIO (https://github.com/NetEase/UnitySocketIO). 8 | 9 | ## How to use 10 | It is very simple to use pomelo-unityclient. Copy all the DLLS locating in the file of /bin/Debug/ 11 | to your project. 12 | 13 | Of course, you can download this project and compile it: 14 | 15 | >git clone https://github.com/NetEase/pomelo-unityclient.git 16 | 17 | ## API 18 | 19 | Create and initialize a new pomelo client. 20 | 21 | ```c# 22 | PomeloClient pclient = new PomeloClient(url); 23 | pclient.init(); 24 | 25 | ``` 26 | 27 | Send request to server and process data in callback. 28 | 29 | ```c# 30 | pclient.request(route, message, (data)=>{ 31 | //process the data 32 | }); 33 | ``` 34 | Notify server without response 35 | 36 | ```c# 37 | pclient.notify(route, messge); 38 | ``` 39 | Add event listener, process broadcast message 40 | ```c# 41 | pclient.On(route, (data)=>{ 42 | //process the data 43 | }); 44 | ``` 45 | Disconnect the client. 46 | ```c# 47 | pclient.disconnect(); 48 | ``` 49 | ##License 50 | (The MIT License) 51 | 52 | Copyright (c) 2012-2013 NetEase, Inc. and other contributors 53 | 54 | Permission is hereby granted, free of charge, to any person obtaining a 55 | copy of this software and associated documentation files (the 'Software'), 56 | to deal in the Software without restriction, including without limitation 57 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 58 | and/or sell copies of the Software, and to permit persons to whom the 59 | Software is furnished to do so, subject to the following conditions: 60 | 61 | The above copyright notice and this permission notice shall be included in 62 | all copies or substantial portions of the Software. 63 | 64 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 65 | -------------------------------------------------------------------------------- /pomelo-unityclient.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 10.00 3 | # Visual Studio 2008 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pomelo-unityclient", "pomelo-unityclient\pomelo-unityclient.csproj", "{E31589A2-F031-42F7-B809-FED22BB6EC30}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|x86 = Debug|x86 9 | Release|x86 = Release|x86 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {E31589A2-F031-42F7-B809-FED22BB6EC30}.Debug|x86.ActiveCfg = Debug|x86 13 | {E31589A2-F031-42F7-B809-FED22BB6EC30}.Debug|x86.Build.0 = Debug|x86 14 | {E31589A2-F031-42F7-B809-FED22BB6EC30}.Release|x86.ActiveCfg = Release|x86 15 | {E31589A2-F031-42F7-B809-FED22BB6EC30}.Release|x86.Build.0 = Release|x86 16 | EndGlobalSection 17 | GlobalSection(MonoDevelopProperties) = preSolution 18 | StartupItem = pomelo-unityclient\pomelo-unityclient.csproj 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /pomelo-unityclient.userprefs: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /pomelo-unityclient/bin/Debug/SimpleJson.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NetEase/pomelo-unityclient/f276c3edacde8a8d8f320a245e3c212ecfdb3bbe/pomelo-unityclient/bin/Debug/SimpleJson.dll -------------------------------------------------------------------------------- /pomelo-unityclient/bin/Debug/SocketIO.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NetEase/pomelo-unityclient/f276c3edacde8a8d8f320a245e3c212ecfdb3bbe/pomelo-unityclient/bin/Debug/SocketIO.dll -------------------------------------------------------------------------------- /pomelo-unityclient/bin/Debug/SuperSocket.ClientEngine.Common.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NetEase/pomelo-unityclient/f276c3edacde8a8d8f320a245e3c212ecfdb3bbe/pomelo-unityclient/bin/Debug/SuperSocket.ClientEngine.Common.dll -------------------------------------------------------------------------------- /pomelo-unityclient/bin/Debug/SuperSocket.ClientEngine.Core.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NetEase/pomelo-unityclient/f276c3edacde8a8d8f320a245e3c212ecfdb3bbe/pomelo-unityclient/bin/Debug/SuperSocket.ClientEngine.Core.dll -------------------------------------------------------------------------------- /pomelo-unityclient/bin/Debug/SuperSocket.ClientEngine.Protocol.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NetEase/pomelo-unityclient/f276c3edacde8a8d8f320a245e3c212ecfdb3bbe/pomelo-unityclient/bin/Debug/SuperSocket.ClientEngine.Protocol.dll -------------------------------------------------------------------------------- /pomelo-unityclient/bin/Debug/SuperSocket.ClientEngine.Proxy.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NetEase/pomelo-unityclient/f276c3edacde8a8d8f320a245e3c212ecfdb3bbe/pomelo-unityclient/bin/Debug/SuperSocket.ClientEngine.Proxy.dll -------------------------------------------------------------------------------- /pomelo-unityclient/bin/Debug/WebSocket4Net.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NetEase/pomelo-unityclient/f276c3edacde8a8d8f320a245e3c212ecfdb3bbe/pomelo-unityclient/bin/Debug/WebSocket4Net.dll -------------------------------------------------------------------------------- /pomelo-unityclient/bin/Debug/pomelo-unityclient.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NetEase/pomelo-unityclient/f276c3edacde8a8d8f320a245e3c212ecfdb3bbe/pomelo-unityclient/bin/Debug/pomelo-unityclient.dll -------------------------------------------------------------------------------- /pomelo-unityclient/bin/Debug/pomelo-unityclient.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NetEase/pomelo-unityclient/f276c3edacde8a8d8f320a245e3c212ecfdb3bbe/pomelo-unityclient/bin/Debug/pomelo-unityclient.pdb -------------------------------------------------------------------------------- /pomelo-unityclient/pomelo-unityclient.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | x86 6 | 9.0.21022 7 | 2.0 8 | {E31589A2-F031-42F7-B809-FED22BB6EC30} 9 | Library 10 | pomelounityclient 11 | pomelo-unityclient 12 | v3.5 13 | 14 | 15 | true 16 | full 17 | false 18 | bin\Debug 19 | DEBUG; 20 | prompt 21 | 4 22 | x86 23 | false 24 | 25 | 26 | none 27 | false 28 | bin\Release 29 | prompt 30 | 4 31 | x86 32 | false 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | ..\..\..\Chat\Assets\Plugins\SimpleJson.dll 43 | 44 | 45 | ..\..\..\Chat\Assets\Plugins\SocketIO.dll 46 | 47 | 48 | ..\..\..\Chat\Assets\Plugins\SuperSocket.ClientEngine.Common.dll 49 | 50 | 51 | ..\..\..\Chat\Assets\Plugins\SuperSocket.ClientEngine.Core.dll 52 | 53 | 54 | ..\..\..\Chat\Assets\Plugins\SuperSocket.ClientEngine.Protocol.dll 55 | 56 | 57 | ..\..\..\Chat\Assets\Plugins\SuperSocket.ClientEngine.Proxy.dll 58 | 59 | 60 | ..\..\..\Chat\Assets\Plugins\WebSocket4Net.dll 61 | 62 | 63 | -------------------------------------------------------------------------------- /pomelo-unityclient/pomelo-unityclient.pidb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NetEase/pomelo-unityclient/f276c3edacde8a8d8f320a245e3c212ecfdb3bbe/pomelo-unityclient/pomelo-unityclient.pidb -------------------------------------------------------------------------------- /pomelo-unityclient/pomelo-unityclient/EventManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Concurrent; 3 | using System.Collections.Generic; 4 | using System.Diagnostics; 5 | using System.Linq; 6 | using System.Text; 7 | using SocketIOClient.Messages; 8 | using SimpleJson; 9 | 10 | namespace pomeloUnityClient 11 | { 12 | public class EventManager : IDisposable 13 | { 14 | 15 | private Dictionary> callBackMap; 16 | private Dictionary>> eventMap; 17 | 18 | public EventManager() 19 | { 20 | this.callBackMap = new Dictionary>(); 21 | this.eventMap = new Dictionary>>(); 22 | } 23 | 24 | //Adds callback to callBackMap by id. 25 | public void AddCallBack(int id, Action callback) 26 | { 27 | if (id != null && callback != null) { 28 | this.callBackMap.Add(id, callback); 29 | } 30 | } 31 | 32 | /// 33 | /// Invoke the callback when the server return messge . 34 | /// 35 | /// 36 | /// Pomelo message. 37 | /// 38 | public void InvokeCallBack(JsonObject msg) 39 | { 40 | if (msg != null) { 41 | Action action = null; 42 | object id = null; 43 | object body = null; 44 | if (msg.TryGetValue("id", out id)){ 45 | if(this.callBackMap.TryGetValue(Convert.ToInt32(id), out action)) { 46 | if (msg.TryGetValue("body", out body)) { 47 | action.Invoke((JsonObject)SimpleJson.SimpleJson.DeserializeObject(body.ToString())); 48 | } 49 | } 50 | } 51 | } 52 | } 53 | 54 | //Adds the event to eventMap by name. 55 | public void AddOnEvent(string eventName, Action callback) 56 | { 57 | List> list = null; 58 | if (this.eventMap.TryGetValue(eventName, out list)) { 59 | list.Add(callback); 60 | } else { 61 | list = new List>(); 62 | list.Add(callback); 63 | this.eventMap.Add(eventName, list); 64 | } 65 | } 66 | 67 | /// 68 | /// If the event exists,invoke the event when server return messge. 69 | /// 70 | /// 71 | /// 72 | /// 73 | /// 74 | public void InvokeOnEvent (JsonObject msg) { 75 | List> list = null; 76 | object route = null; 77 | if (msg.TryGetValue("route", out route)) { 78 | if (this.eventMap.TryGetValue(route.ToString(), out list)) { 79 | int length = list.Count; 80 | for(int i = 0; i < length; i++) { 81 | Action ap = list[i]; 82 | ap.Invoke(msg); 83 | } 84 | } 85 | } 86 | } 87 | 88 | 89 | // Dispose() calls Dispose(true) 90 | public void Dispose() 91 | { 92 | Dispose(true); 93 | GC.SuppressFinalize(this); 94 | } 95 | 96 | // The bulk of the clean-up code is implemented in Dispose(bool) 97 | protected void Dispose(bool disposing) 98 | { 99 | this.callBackMap.Clear(); 100 | this.eventMap.Clear(); 101 | } 102 | } 103 | } 104 | 105 | -------------------------------------------------------------------------------- /pomelo-unityclient/pomelo-unityclient/PomeloClient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using System.Diagnostics; 4 | using SimpleJson; 5 | using System.Collections.Generic; 6 | using SocketIOClient; 7 | 8 | namespace pomeloUnityClient 9 | { 10 | public class PomeloClient 11 | { 12 | private Client socket = null; 13 | private int reqId = 0; 14 | private const string ARRAY_FLAG = "["; 15 | private const string URL_HEADER = "http://"; 16 | private EventManager eventManager = null; 17 | 18 | public PomeloClient (string url) 19 | { 20 | string checkedUrl = this.checkUrl(url); 21 | 22 | try{ 23 | this.socket = new Client(checkedUrl); 24 | } catch (Exception e) { 25 | Console.WriteLine(string.Format("Error in new SocketIO:{0}", e.Message)); 26 | } 27 | 28 | this.eventManager = new EventManager(); 29 | } 30 | 31 | //Init socket and make connection. 32 | public void init(){ 33 | 34 | this.socket.Opened += this.SocketOpened; 35 | this.socket.Message += this.SocketMessage; 36 | this.socket.SocketConnectionClosed += this.SocketConnectionClosed; 37 | this.socket.Error += this.SocketError; 38 | 39 | this.socket.Connect(); 40 | } 41 | 42 | //Check out the url and complemented it. 43 | private string checkUrl(string url){ 44 | string trueUrl; 45 | 46 | if (!url.Contains(URL_HEADER)) { 47 | trueUrl = URL_HEADER + url; 48 | } else { 49 | trueUrl = url; 50 | } 51 | 52 | return trueUrl; 53 | } 54 | 55 | //Close the socket and free the resources. 56 | public void disconnect(){ 57 | this.socket.Close(); 58 | if (this.eventManager != null) { 59 | this.eventManager.Dispose(); 60 | this.eventManager = null; 61 | } 62 | this.closeSocketIO(); 63 | 64 | } 65 | 66 | /// 67 | /// Sends the message to server. 68 | /// 69 | /// 70 | /// Req identifier. 71 | /// 72 | /// 73 | /// Route. 74 | /// 75 | /// 76 | /// Message. 77 | /// 78 | private void sendMessage(int reqId, string route, JsonObject msg){ 79 | string message = ""; 80 | try{ 81 | message = Protocol.encode(reqId, route, msg); 82 | }catch(ArgumentException e) { 83 | Console.WriteLine(string.Format("Error in protocol.encode:{0}", e.Message)); 84 | } 85 | 86 | this.socket.Send(message); 87 | } 88 | 89 | /// 90 | /// Request message from server and register callback. 91 | /// 92 | /// 93 | /// Route. 94 | /// 95 | /// 96 | /// Message. 97 | /// 98 | /// 99 | /// Action. 100 | /// 101 | public void request(string route, JsonObject msg, Action action){ 102 | 103 | JsonObject returnMSg = filter(msg); 104 | reqId++; 105 | this.eventManager.AddCallBack(reqId, action); 106 | this.sendMessage(reqId, route, returnMSg); 107 | 108 | } 109 | 110 | //Notify message to server. 111 | public void notify(string route, JsonObject msg) { 112 | this.sendMessage(0, route, msg); 113 | } 114 | 115 | //Listen evetn named eventName. 116 | public void On(string eventName, Action action){ 117 | this.eventManager.AddOnEvent(eventName, action); 118 | } 119 | 120 | //Add msg time. 121 | private JsonObject filter(JsonObject msg) { 122 | if (msg == null) { 123 | msg = new JsonObject(); 124 | } 125 | var st= new DateTime(1970,1,1); 126 | TimeSpan t= (DateTime.Now.ToUniversalTime()-st); 127 | Int64 retval= (Int64)(t.TotalMilliseconds+0.5); 128 | msg.Add("timestamp", retval); 129 | return msg; 130 | } 131 | 132 | /// 133 | /// Processes the message and invoke callback or event. 134 | /// 135 | /// 136 | /// Message. 137 | /// 138 | private void processMessage(string msg){ 139 | JsonObject jsonMsg = (JsonObject)SimpleJson.SimpleJson.DeserializeObject(msg); 140 | Object id = null; 141 | //-----------the request and notify message from server----------------- 142 | if (jsonMsg.TryGetValue("id", out id)) { 143 | this.eventManager.InvokeCallBack(jsonMsg); 144 | //------------bordcast message form server------------------------------ 145 | } else { 146 | this.eventManager.InvokeOnEvent(jsonMsg); 147 | } 148 | } 149 | 150 | //Processes the message and invoke callback or event. 151 | private void processMessageBatch(string msgs){ 152 | JsonArray jsonArray = (JsonArray) SimpleJson.SimpleJson.DeserializeObject(msgs); 153 | int length = jsonArray.Count; 154 | for (int i = 0; i < length; i++) { 155 | this.processMessage(jsonArray[i].ToString()); 156 | } 157 | } 158 | 159 | //Free the resources 160 | private void closeSocketIO(){ 161 | if (this.socket != null) { 162 | this.socket.Opened -= this.SocketOpened; 163 | this.socket.Message -= this.SocketMessage; 164 | this.socket.SocketConnectionClosed -= this.SocketConnectionClosed; 165 | this.socket.Error -= this.SocketError; 166 | 167 | this.socket = null; 168 | } 169 | } 170 | 171 | //connection opened event. 172 | private void SocketOpened (object sender, EventArgs e){ 173 | Console.WriteLine("The socketIO opend!"); 174 | } 175 | /// 176 | /// When message from server comes, it invoke. 177 | /// 178 | /// 179 | /// Sender. 180 | /// 181 | /// 182 | /// E. 183 | /// 184 | private void SocketMessage (object sender, MessageEventArgs e) { 185 | 186 | if ( e!= null && e.Message.Event == "message") { 187 | string msg = e.Message.MessageText; 188 | if (msg.IndexOf(ARRAY_FLAG) == 0) { 189 | this.processMessageBatch(msg); 190 | } else { 191 | this.processMessage(msg); 192 | } 193 | } 194 | } 195 | 196 | //Connetction close event. 197 | private void SocketConnectionClosed (object sender, EventArgs e) { 198 | Console.WriteLine("WebSocketConnection was terminated!"); 199 | } 200 | 201 | //Connection error event. 202 | private void SocketError (object sender, ErrorEventArgs e) { 203 | Console.WriteLine("socket client error:"); 204 | Console.WriteLine(e.Message); 205 | } 206 | } 207 | } 208 | 209 | -------------------------------------------------------------------------------- /pomelo-unityclient/pomelo-unityclient/Protocol.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using SimpleJson; 4 | using System.Diagnostics; 5 | 6 | namespace pomeloUnityClient 7 | { 8 | public class Protocol 9 | { 10 | private const int HEADER = 5; 11 | 12 | public Protocol () 13 | { 14 | 15 | } 16 | /// 17 | /// Encode the messge with id, route and jsonObject. 18 | /// 19 | /// 20 | /// Identifier. 21 | /// 22 | /// 23 | /// Route. 24 | /// 25 | /// 26 | /// Json object. 27 | /// 28 | /// 29 | /// Is thrown when the argument exception. 30 | /// 31 | public static string encode(int id, string route, JsonObject jsonObject){ 32 | 33 | if (route.Length > 255) { 34 | throw new System.ArgumentException("route maxlength is overflow"); 35 | } 36 | 37 | byte[] byteArray = new byte[HEADER + route.Length]; 38 | int index = 0; 39 | byteArray[index++] = Convert.ToByte((id >> 24) & 0xFF); 40 | byteArray[index++] = Convert.ToByte((id >> 16) & 0xFF); 41 | byteArray[index++] = Convert.ToByte((id >> 8) & 0xFF); 42 | byteArray[index++] = Convert.ToByte(id & 0xFF); 43 | byteArray[index++] = Convert.ToByte(route.Length & 0xFF); 44 | 45 | char[] routeArray = route.ToCharArray(); 46 | int routeLength = routeArray.Length; 47 | for(int i = 0; i < routeLength; i++) { 48 | byteArray[index++] = Convert.ToByte(routeArray[i]); 49 | } 50 | string encodeString = ""; 51 | try{ 52 | encodeString = Encoding.UTF8.GetString(byteArray); 53 | }catch(Exception e){ 54 | Console.WriteLine(string.Format("Error in new Encoding.UTF8.GetString:{0}", e.Message)); 55 | } 56 | return encodeString + jsonObject.ToString(); 57 | } 58 | 59 | } 60 | } 61 | 62 | --------------------------------------------------------------------------------