SocketIOWePlaySample.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. #if !BESTHTTP_DISABLE_SOCKETIO
  2. using System;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5. using BestHTTP.SocketIO;
  6. using BestHTTP.Examples;
  7. public sealed class SocketIOWePlaySample : MonoBehaviour
  8. {
  9. /// <summary>
  10. /// Possible states of the game.
  11. /// </summary>
  12. enum States
  13. {
  14. Connecting,
  15. WaitForNick,
  16. Joined
  17. }
  18. /// <summary>
  19. /// Controls that the server understands as a parameter in the move event.
  20. /// </summary>
  21. private string[] controls = new string[] { "left", "right", "a", "b", "up", "down", "select", "start" };
  22. /// <summary>
  23. /// Ratio of the drawn GUI texture from the screen
  24. /// </summary>
  25. private const float ratio = 1.5f;
  26. /// <summary>
  27. /// How many messages to keep.
  28. /// </summary>
  29. private int MaxMessages = 50;
  30. /// <summary>
  31. /// Current state of the game.
  32. /// </summary>
  33. private States State;
  34. /// <summary>
  35. /// The root("/") Socket instance.
  36. /// </summary>
  37. private Socket Socket;
  38. /// <summary>
  39. /// The user-selected nickname.
  40. /// </summary>
  41. private string Nick = string.Empty;
  42. /// <summary>
  43. /// The message that the user want to send to the chat.
  44. /// </summary>
  45. private string messageToSend = string.Empty;
  46. /// <summary>
  47. /// How many user connected to the server.
  48. /// </summary>
  49. private int connections;
  50. /// <summary>
  51. /// Local and server sent messages.
  52. /// </summary>
  53. private List<string> messages = new List<string>();
  54. /// <summary>
  55. /// The chat scroll position.
  56. /// </summary>
  57. private Vector2 scrollPos;
  58. /// <summary>
  59. /// The decoded texture from the server sent binary data
  60. /// </summary>
  61. private Texture2D FrameTexture;
  62. #region Unity Events
  63. void Start()
  64. {
  65. // Change an option to show how it should be done
  66. SocketOptions options = new SocketOptions();
  67. options.AutoConnect = false;
  68. // Create the SocketManager instance
  69. var manager = new SocketManager(new Uri("http://io.weplay.io/socket.io/"), options);
  70. // Keep a reference to the root namespace
  71. Socket = manager.Socket;
  72. // Set up our event handlers.
  73. Socket.On(SocketIOEventTypes.Connect, OnConnected);
  74. Socket.On("joined", OnJoined);
  75. Socket.On("connections", OnConnections);
  76. Socket.On("join", OnJoin);
  77. Socket.On("move", OnMove);
  78. Socket.On("message", OnMessage);
  79. Socket.On("reload", OnReload);
  80. // Don't waste cpu cycles on decoding the payload, we are expecting only binary data with this event,
  81. // and we can access it through the packet's Attachments property.
  82. Socket.On("frame", OnFrame, /*autoDecodePayload:*/ false);
  83. // Add error handler, so we can display it
  84. Socket.On(SocketIOEventTypes.Error, OnError);
  85. // We set SocketOptions' AutoConnect to false, so we have to call it manually.
  86. manager.Open();
  87. // We are connecting to the server.
  88. State = States.Connecting;
  89. }
  90. void OnDestroy()
  91. {
  92. // Leaving this sample, close the socket
  93. Socket.Manager.Close();
  94. }
  95. void Update()
  96. {
  97. // Go back to the demo selector
  98. if (Input.GetKeyDown(KeyCode.Escape))
  99. SampleSelector.SelectedSample.DestroyUnityObject();
  100. }
  101. void OnGUI()
  102. {
  103. switch(State)
  104. {
  105. case States.Connecting:
  106. GUIHelper.DrawArea(GUIHelper.ClientArea, true, () =>
  107. {
  108. GUILayout.BeginVertical();
  109. GUILayout.FlexibleSpace();
  110. GUIHelper.DrawCenteredText("Connecting to the server...");
  111. GUILayout.FlexibleSpace();
  112. GUILayout.EndVertical();
  113. });
  114. break;
  115. case States.WaitForNick:
  116. GUIHelper.DrawArea(GUIHelper.ClientArea, true, () =>
  117. {
  118. DrawLoginScreen();
  119. });
  120. break;
  121. case States.Joined:
  122. GUIHelper.DrawArea(GUIHelper.ClientArea, true, () =>
  123. {
  124. // Draw Texture
  125. if (FrameTexture != null)
  126. GUILayout.Box(FrameTexture);
  127. DrawControls();
  128. DrawChat();
  129. });
  130. break;
  131. }
  132. }
  133. #endregion
  134. #region Helper Functions
  135. /// <summary>
  136. /// Called from an OnGUI event to draw the Login Screen.
  137. /// </summary>
  138. void DrawLoginScreen()
  139. {
  140. GUILayout.BeginVertical();
  141. GUILayout.FlexibleSpace();
  142. GUIHelper.DrawCenteredText("What's your nickname?");
  143. Nick = GUILayout.TextField(Nick);
  144. if (GUILayout.Button("Join"))
  145. Join();
  146. GUILayout.FlexibleSpace();
  147. GUILayout.EndVertical();
  148. }
  149. void DrawControls()
  150. {
  151. GUILayout.BeginHorizontal();
  152. GUILayout.Label("Controls:");
  153. for (int i = 0; i < controls.Length; ++i)
  154. if (GUILayout.Button(controls[i]))
  155. Socket.Emit("move", controls[i]);
  156. GUILayout.Label(" Connections: " + connections);
  157. GUILayout.EndHorizontal();
  158. }
  159. void DrawChat(bool withInput = true)
  160. {
  161. GUILayout.BeginVertical();
  162. // Draw the messages
  163. scrollPos = GUILayout.BeginScrollView(scrollPos, false, false);
  164. for (int i = 0; i < messages.Count; ++i)
  165. GUILayout.Label(messages[i], GUILayout.MinWidth(Screen.width));
  166. GUILayout.EndScrollView();
  167. if (withInput)
  168. {
  169. GUILayout.Label("Your message: ");
  170. GUILayout.BeginHorizontal();
  171. messageToSend = GUILayout.TextField(messageToSend);
  172. if (GUILayout.Button("Send", GUILayout.MaxWidth(100)))
  173. SendMessage();
  174. GUILayout.EndHorizontal();
  175. }
  176. GUILayout.EndVertical();
  177. }
  178. /// <summary>
  179. /// Add a message to the message log
  180. /// </summary>
  181. /// <param name="msg"></param>
  182. void AddMessage(string msg)
  183. {
  184. messages.Insert(0, msg);
  185. if (messages.Count > MaxMessages)
  186. messages.RemoveRange(MaxMessages, messages.Count - MaxMessages);
  187. }
  188. /// <summary>
  189. /// Send a chat message. The message must be in the messageToSend field.
  190. /// </summary>
  191. void SendMessage()
  192. {
  193. if (string.IsNullOrEmpty(messageToSend))
  194. return;
  195. Socket.Emit("message", messageToSend);
  196. AddMessage(string.Format("{0}: {1}", Nick, messageToSend));
  197. messageToSend = string.Empty;
  198. }
  199. /// <summary>
  200. /// Join to the game with the nickname stored in the Nick field.
  201. /// </summary>
  202. void Join()
  203. {
  204. PlayerPrefs.SetString("Nick", Nick);
  205. Socket.Emit("join", Nick);
  206. }
  207. /// <summary>
  208. /// Reload the game.
  209. /// </summary>
  210. void Reload()
  211. {
  212. FrameTexture = null;
  213. if (Socket != null)
  214. {
  215. Socket.Manager.Close();
  216. Socket = null;
  217. Start();
  218. }
  219. }
  220. #endregion
  221. #region SocketIO Events
  222. /// <summary>
  223. /// Socket connected event.
  224. /// </summary>
  225. private void OnConnected(Socket socket, Packet packet, params object[] args)
  226. {
  227. if (PlayerPrefs.HasKey("Nick"))
  228. {
  229. Nick = PlayerPrefs.GetString("Nick", "NickName");
  230. Join();
  231. }
  232. else
  233. State = States.WaitForNick;
  234. AddMessage("connected");
  235. }
  236. /// <summary>
  237. /// Local player joined after sending a 'join' event
  238. /// </summary>
  239. private void OnJoined(Socket socket, Packet packet, params object[] args)
  240. {
  241. State = States.Joined;
  242. }
  243. /// <summary>
  244. /// Server sent us a 'reload' event.
  245. /// </summary>
  246. private void OnReload(Socket socket, Packet packet, params object[] args)
  247. {
  248. Reload();
  249. }
  250. /// <summary>
  251. /// Someone wrote a message to the chat.
  252. /// </summary>
  253. private void OnMessage(Socket socket, Packet packet, params object[] args)
  254. {
  255. if (args.Length == 1)
  256. AddMessage(args[0] as string);
  257. else
  258. AddMessage(string.Format("{0}: {1}", args[1], args[0]));
  259. }
  260. /// <summary>
  261. /// Someone (including us) pressed a button.
  262. /// </summary>
  263. private void OnMove(Socket socket, Packet packet, params object[] args)
  264. {
  265. AddMessage(string.Format("{0} pressed {1}", args[1], args[0]));
  266. }
  267. /// <summary>
  268. /// Someone joined to the game
  269. /// </summary>
  270. private void OnJoin(Socket socket, Packet packet, params object[] args)
  271. {
  272. string loc = args.Length > 1 ? string.Format("({0})", args[1]) : string.Empty;
  273. AddMessage(string.Format("{0} joined {1}", args[0], loc));
  274. }
  275. /// <summary>
  276. /// How many players are connected to the game.
  277. /// </summary>
  278. private void OnConnections(Socket socket, Packet packet, params object[] args)
  279. {
  280. connections = Convert.ToInt32(args[0]);
  281. }
  282. /// <summary>
  283. /// The server sent us a new picture to draw the game.
  284. /// </summary>
  285. private void OnFrame(Socket socket, Packet packet, params object[] args)
  286. {
  287. if (State != States.Joined)
  288. return;
  289. if (FrameTexture == null)
  290. {
  291. FrameTexture = new Texture2D(0, 0, TextureFormat.RGBA32, false);
  292. FrameTexture.filterMode = FilterMode.Point;
  293. }
  294. // Binary data usage case 1 - using directly the Attachments property:
  295. byte[] data = packet.Attachments[0];
  296. // Binary data usage case 2 - using the packet's ReconstructAttachmentAsIndex() function
  297. /*packet.ReconstructAttachmentAsIndex();
  298. args = packet.Decode(socket.Manager.Encoder);
  299. data = packet.Attachments[Convert.ToInt32(args[0])];*/
  300. // Binary data usage case 3 - using the packet's ReconstructAttachmentAsBase64() function
  301. /*packet.ReconstructAttachmentAsBase64();
  302. args = packet.Decode(socket.Manager.Encoder);
  303. data = Convert.FromBase64String(args[0] as string);*/
  304. // Load the server sent picture
  305. FrameTexture.LoadImage(data);
  306. }
  307. /// <summary>
  308. /// Called on local or remote error.
  309. /// </summary>
  310. private void OnError(Socket socket, Packet packet, params object[] args)
  311. {
  312. AddMessage(string.Format("--ERROR - {0}", args[0].ToString()));
  313. }
  314. #endregion
  315. }
  316. #endif