SocketIOWePlaySample.cs 12 KB

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