using System;
namespace BestHTTP.Examples
{
///
using System; using System.Collections.Generic; using UnityEngine; using BestHTTP; public sealed class TextureDownloadSample : MonoBehaviour { /// <summary> /// The URL of the server that will serve the image resources /// </summary> const string BaseURL = "http://besthttp.azurewebsites.net/Content/"; #region Private Fields /// <summary> /// The downloadable images /// </summary> string[] Images = new string[9] { "One.png", "Two.png", "Three.png", "Four.png", "Five.png", "Six.png", "Seven.png", "Eight.png", "Nine.png" }; /// <summary> /// The downloaded images will be stored as textures in this array /// </summary> Texture2D[] Textures = new Texture2D[9]; /// <summary> /// True if all images are loaded from the local cache instead of the server /// </summary> bool allDownloadedFromLocalCache; /// <summary> /// How many sent requests are finished /// </summary> int finishedCount; /// <summary> /// GUI scroll position /// </summary> Vector2 scrollPos; #endregion #region Unity Events void Awake() { // SaveLocal a well observable value // This is how many concurrent requests can be made to a server HTTPManager.MaxConnectionPerServer = 1; // Create placeholder textures for (int i = 0; i < Images.Length; ++i) Textures[i] = new Texture2D(100, 150); } void OnDestroy() { // SaveLocal back to its defualt value. HTTPManager.MaxConnectionPerServer = 4; } void OnGUI() { GUIHelper.DrawArea(GUIHelper.ClientArea, true, () => { scrollPos = GUILayout.BeginScrollView(scrollPos); // Draw out the textures GUILayout.SelectionGrid(0, Textures, 3); if (finishedCount == Images.Length && allDownloadedFromLocalCache) GUIHelper.DrawCenteredText("All images loaded from the local cache!"); GUILayout.FlexibleSpace(); GUILayout.BeginHorizontal(); GUILayout.Label("Max Connection/Server: ", GUILayout.Width(150)); GUILayout.Label(HTTPManager.MaxConnectionPerServer.ToString(), GUILayout.Width(20)); HTTPManager.MaxConnectionPerServer = (byte)GUILayout.HorizontalSlider(HTTPManager.MaxConnectionPerServer, 1, 10); GUILayout.EndHorizontal(); if (GUILayout.Button("Start Download")) DownloadImages(); GUILayout.EndScrollView(); }); } #endregion #region Private Helper Functions void DownloadImages() { // SaveLocal these metadatas to its initial values allDownloadedFromLocalCache = true; finishedCount = 0; for (int i = 0; i < Images.Length; ++i) { // SaveLocal a blank placeholder texture, overriding previously downloaded texture Textures[i] = new Texture2D(100, 150); // Construct the request var request = new HTTPRequest(new Uri(BaseURL + Images[i]), ImageDownloaded); // SaveLocal the Tag property, we can use it as a general storage bound to the request request.Tag = Textures[i]; // Send out the request request.Send(); } } /// <summary> /// Callback function of the image download http requests /// </summary> void ImageDownloaded(HTTPRequest req, HTTPResponse resp) { // Increase the finished count regardless of the state of our request finishedCount++; switch (req.State) { // The request finished without any problem. case HTTPRequestStates.Finished: if (resp.IsSuccess) { // Get the Texture from the Tag property Texture2D tex = req.Tag as Texture2D; // Load the texture tex.LoadImage(resp.Data); // Update the cache-info variable allDownloadedFromLocalCache = allDownloadedFromLocalCache && resp.IsFromCache; } else { Debug.LogWarning(string.Format("Request finished Successfully, but the server sent an error. Status Code: {0}-{1} Message: {2}", resp.StatusCode, resp.Message, resp.DataAsText)); } break; // The request finished with an unexpected error. The request's Exception property may contain more info about the error. case HTTPRequestStates.Error: Debug.LogError("Request Finished with Error! " + (req.Exception != null ? (req.Exception.Message + "\n" + req.Exception.StackTrace) : "No Exception")); break; // The request aborted, initiated by the user. case HTTPRequestStates.Aborted: Debug.LogWarning("Request Aborted!"); break; // Ceonnecting to the server is timed out. case HTTPRequestStates.ConnectionTimedOut: Debug.LogError("Connection Timed Out!"); break; // The request didn't finished in the given time. case HTTPRequestStates.TimedOut: Debug.LogError("Processing the request Timed Out!"); break; } } #endregion }"; #endregion #region WebSocketSample public static string WebSocketSample = @"
using System; using UnityEngine; using BestHTTP; using BestHTTP.WebSocket; public class WebSocketSample : MonoBehaviour { #region Private Fields /// <summary> /// The WebSocket address to connect /// </summary> string address = "ws://echo.websocket.org"; /// <summary> /// Default text to send /// </summary> string msgToSend = "Hello World!"; /// <summary> /// Debug text to draw on the gui /// </summary> string Text = string.Empty; /// <summary> /// Saved WebSocket instance /// </summary> WebSocket webSocket; /// <summary> /// GUI scroll position /// </summary> Vector2 scrollPos; #endregion #region Unity Events void OnDestroy() { if (webSocket != null) webSocket.Close(); } void OnGUI() { GUIHelper.DrawArea(GUIHelper.ClientArea, true, () => { scrollPos = GUILayout.BeginScrollView(scrollPos); GUILayout.Label(Text); GUILayout.EndScrollView(); GUILayout.Space(5); GUILayout.FlexibleSpace(); address = GUILayout.TextField(address); if (webSocket == null && GUILayout.Button("Open Web Socket")) { // Create the WebSocket instance webSocket = new WebSocket(new Uri(address)); if (HTTPManager.Proxy != null) webSocket.InternalRequest.Proxy = new HTTPProxy(HTTPManager.Proxy.Address, HTTPManager.Proxy.Credentials, false); // Subscribe to the WS events webSocket.OnOpen += OnOpen; webSocket.OnMessage += OnMessageReceived; webSocket.OnClosed += OnClosed; webSocket.OnError += OnError; // Start connecting to the server webSocket.Open(); Text += "Opening Web Socket...\n"; } if (webSocket != null && webSocket.IsOpen) { GUILayout.Space(10); GUILayout.BeginHorizontal(); msgToSend = GUILayout.TextField(msgToSend); if (GUILayout.Button("Send", GUILayout.MaxWidth(70))) { Text += "Sending message...\n"; // Send message to the server webSocket.Send(msgToSend); } GUILayout.EndHorizontal(); GUILayout.Space(10); if (GUILayout.Button("Close")) { // Close the connection webSocket.Close(1000, "Bye!"); } } }); } #endregion #region WebSocket Event Handlers /// <summary> /// Called when the web socket is open, and we are ready to send and receive data /// </summary> void OnOpen(WebSocket ws) { Text += string.Format("-WebSocket Open!\n"); } /// <summary> /// Called when we received a text message from the server /// </summary> void OnMessageReceived(WebSocket ws, string message) { Text += string.Format("-Message received: {0}\n", message); } /// <summary> /// Called when the web socket closed /// </summary> void OnClosed(WebSocket ws, UInt16 code, string message) { Text += string.Format("-WebSocket closed! Code: {0} Message: {1}\n", code, message); webSocket = null; } /// <summary> /// Called when an error occured on client side /// </summary> void OnError(WebSocket ws, Exception ex) { string errorMsg = string.Empty; if (ws.InternalRequest.Response != null) errorMsg = string.Format("Status Code from Server: {0} and Message: {1}", ws.InternalRequest.Response.StatusCode, ws.InternalRequest.Response.Message); Text += string.Format("-An error occured: {0}\n", (ex != null ? ex.Message : "Unknown Error " + errorMsg)); webSocket = null; } #endregion }"; #endregion #region AssetBundleSample public static string AssetBundleSample = @"
using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using BestHTTP; public sealed class AssetBundleSample : MonoBehaviour { /// <summary> /// The url of the resource to download /// </summary> const string URL = "http://besthttp.azurewebsites.net/Content/AssetBundle.html"; #region Private Fields /// <summary> /// Debug status text /// </summary> string status = "Waiting for user interaction"; /// <summary> /// The downloaded and cached AssetBundle /// </summary> AssetBundle cachedBundle; /// <summary> /// The loaded texture from the AssetBundle /// </summary> Texture2D texture; /// <summary> /// A flag that indicates that we are processing the request/bundle to hide the "Start Download" button. /// </summary> bool downloading; #endregion #region Unity Events void OnGUI() { GUIHelper.DrawArea(GUIHelper.ClientArea, true, () => { GUILayout.Label("Status: " + status); // Draw the texture from the downloaded bundle if (texture != null) GUILayout.Box(texture, GUILayout.MaxHeight(256)); if (!downloading && GUILayout.Button("Start Download")) { UnloadBundle(); StartCoroutine(DownloadAssetBundle()); } }); } void OnDestroy() { UnloadBundle(); } #endregion #region Private Helper Functions IEnumerator DownloadAssetBundle() { downloading = true; // Create and send our request var request = new HTTPRequest(new Uri(URL)).Send(); status = "Download started"; // Wait while it's finishes and add some fancy dots to display something while the user waits for it. // A simple "yield return StartCoroutine(request);" would do the job too. while(request.State < HTTPRequestStates.Finished) { yield return new WaitForSeconds(0.1f); status += "."; } // Check the outcome of our request. switch (request.State) { // The request finished without any problem. case HTTPRequestStates.Finished: if (request.Response.IsSuccess) { status = string.Format("AssetBundle downloaded! Loaded from local cache: {0}", request.Response.IsFromCache.ToString()); // Start creating the downloaded asset bundle AssetBundleCreateRequest async = AssetBundle.CreateFromMemory(request.Response.Data); // wait for it yield return async; // And process the bundle yield return StartCoroutine(ProcessAssetBundle(async.assetBundle)); } else { status = string.Format("Request finished Successfully, but the server sent an error. Status Code: {0}-{1} Message: {2}", request.Response.StatusCode, request.Response.Message, request.Response.DataAsText); Debug.LogWarning(status); } break; // The request finished with an unexpected error. The request's Exception property may contain more info about the error. case HTTPRequestStates.Error: status = "Request Finished with Error! " + (request.Exception != null ? (request.Exception.Message + "\n" + request.Exception.StackTrace) : "No Exception"); Debug.LogError(status); break; // The request aborted, initiated by the user. case HTTPRequestStates.Aborted: status = "Request Aborted!"; Debug.LogWarning(status); break; // Ceonnecting to the server is timed out. case HTTPRequestStates.ConnectionTimedOut: status = "Connection Timed Out!"; Debug.LogError(status); break; // The request didn't finished in the given time. case HTTPRequestStates.TimedOut: status = "Processing the request Timed Out!"; Debug.LogError(status); break; } downloading = false; } /// <summary> /// In this function we can do whatever we want with the freshly downloaded bundle. /// In this example we will cache it for later use, and we will load a texture from it. /// </summary> IEnumerator ProcessAssetBundle(AssetBundle bundle) { if (bundle == null) yield break; // Save the bundle for future use cachedBundle = bundle; // Start loading the asset from the bundle var asyncAsset = cachedBundle.LoadAsync("9443182_orig", typeof(Texture2D)); // wait til load yield return asyncAsset; // get the texture texture = asyncAsset.asset as Texture2D; } void UnloadBundle() { if (cachedBundle != null) { cachedBundle.Unload(true); cachedBundle = null; } } #endregion }"; #endregion #region LargeFileDownloadSample public static string LargeFileDownloadSample = @"
using System; using System.Collections.Generic; using UnityEngine; using BestHTTP; public sealed class LargeFileDownloadSample : MonoBehaviour { /// <summary> /// The url of the resource to download /// </summary> const string URL = "http://ipv4.download.thinkbroadband.com/100MB.zip"; #region Private Fields /// <summary> /// Cached request to be able to abort it /// </summary> HTTPRequest request; /// <summary> /// Debug status of the request /// </summary> string status = string.Empty; /// <summary> /// Download(processing) progress. Its range is between [0..1] /// </summary> float progress; /// <summary> /// The fragment size that we will set to the request /// </summary> int fragmentSize = HTTPResponse.MinBufferSize; #endregion #region Unity Events void Awake() { // If we have a non-finished download, set the progress to the value where we left it if (PlayerPrefs.HasKey("DownloadLength")) progress = PlayerPrefs.GetInt("DownloadProgress") / (float)PlayerPrefs.GetInt("DownloadLength"); } void OnDestroy() { // Stop the download if we are leaving this example if (request != null && request.State < HTTPRequestStates.Finished) { request.OnProgress = null; request.Callback = null; request.Abort(); } } void OnGUI() { GUIHelper.DrawArea(GUIHelper.ClientArea, true, () => { // Draw the current status GUILayout.Label("Request status: " + status); GUILayout.Space(5); // Draw the current progress GUILayout.Label(string.Format("Progress: {0:P2} of {1:N0}Mb", progress, PlayerPrefs.GetInt("DownloadLength") / 1048576 /*1 Mb*/)); GUILayout.HorizontalSlider(progress, 0, 1); GUILayout.Space(50); if (request == null) { // Draw a slider to be able to change the fragment size GUILayout.Label(string.Format("Desired Fragment Size: {0:N} KBytes", fragmentSize / 1024f)); fragmentSize = (int)GUILayout.HorizontalSlider(fragmentSize, HTTPResponse.MinBufferSize, 10 * 1024 * 1024); GUILayout.Space(5); string buttonStr = PlayerPrefs.HasKey("DownloadProgress") ? "Continue Download" : "Start Download"; if (GUILayout.Button(buttonStr)) StreamLargeFileTest(); } else if (request.State == HTTPRequestStates.Processing && GUILayout.Button("Abort Download")) { // Simulate a connection lost request.Abort(); } }); } #endregion #region Private Helper Functions // Calling this function again when the "DownloadProgress" key in the PlayerPrefs present will // continue the download void StreamLargeFileTest() { request = new HTTPRequest(new Uri(URL), (req, resp) => { switch (req.State) { // The request is currently processed. With UseStreaming == true, we can get the streamed fragments here case HTTPRequestStates.Processing: // SaveLocal the DownloadLength, so we can display the progress if (!PlayerPrefs.HasKey("DownloadLength")) { string value = resp.GetFirstHeaderValue("content-length"); if (!string.IsNullOrEmpty(value)) PlayerPrefs.SetInt("DownloadLength", int.Parse(value)); } // Get the fragments, and save them ProcessFragments(resp.GetStreamedFragments()); status = "Processing"; break; // The request finished without any problem. case HTTPRequestStates.Finished: if (resp.IsSuccess) { // Save any remaining fragments ProcessFragments(resp.GetStreamedFragments()); // Completly finished if (resp.IsStreamingFinished) { status = "Streaming finished!"; // We are done, delete the progress key PlayerPrefs.DeleteKey("DownloadProgress"); PlayerPrefs.Save(); request = null; } else status = "Processing"; } else { status = string.Format("Request finished Successfully, but the server sent an error. Status Code: {0}-{1} Message: {2}", resp.StatusCode, resp.Message, resp.DataAsText); Debug.LogWarning(status); request = null; } break; // The request finished with an unexpected error. The request's Exception property may contain more info about the error. case HTTPRequestStates.Error: status = "Request Finished with Error! " + (req.Exception != null ? (req.Exception.Message + "\n" + req.Exception.StackTrace) : "No Exception"); Debug.LogError(status); request = null; break; // The request aborted, initiated by the user. case HTTPRequestStates.Aborted: status = "Request Aborted!"; Debug.LogWarning(status); request = null; break; // Ceonnecting to the server is timed out. case HTTPRequestStates.ConnectionTimedOut: status = "Connection Timed Out!"; Debug.LogError(status); request = null; break; // The request didn't finished in the given time. case HTTPRequestStates.TimedOut: status = "Processing the request Timed Out!"; Debug.LogError(status); request = null; break; } }); // Are there any progress, that we can continue? if (PlayerPrefs.HasKey("DownloadProgress")) // SaveLocal the range header request.SetRangeHeader(PlayerPrefs.GetInt("DownloadProgress")); else // This is a new request PlayerPrefs.SetInt("DownloadProgress", 0); // If we are writing our own file set it true(disable), so don't duplicate it on the filesystem request.DisableCache = true; // We want to access the downloaded bytes while we are still downloading request.UseStreaming = true; // SaveLocal a reasonable high fragment size. Here it is 5 megabytes. request.StreamFragmentSize = fragmentSize; // Start Processing the request request.Send(); } /// <summary> /// In this function we can do whatever we want with the downloaded bytes. In this sample we will do nothing, just set the metadata to display progress. /// </summary> void ProcessFragments(List<byte[]> fragments) { if (fragments != null && fragments.Count > 0) { /*string dir = "TODO!"; string filename = "TODO!"; using (System.IO.FileStream fs = new System.IO.FileStream(System.IO.Path.Combine(dir, filename), System.IO.FileMode.Append)) for (int i = 0; i < fragments.Count; ++i) fs.Write(fragments[i], 0, fragments[i].Length);*/ for (int i = 0; i < fragments.Count; ++i) { // Save how many bytes we wrote successfully int downloaded = PlayerPrefs.GetInt("DownloadProgress") + fragments[i].Length; PlayerPrefs.SetInt("DownloadProgress", downloaded); } PlayerPrefs.Save(); // SaveLocal the progress to the actually processed bytes progress = PlayerPrefs.GetInt("DownloadProgress") / (float)PlayerPrefs.GetInt("DownloadLength"); } } #endregion }"; #endregion #region SocketIOChatSample public static string SocketIOChatSample = @"
using System; using System.Collections.Generic; using UnityEngine; using BestHTTP; using BestHTTP.SocketIO; using BestHTTP.JSON; using BestHTTP.SocketIO.Events; public sealed class SocketIOChatSample : MonoBehaviour { private readonly TimeSpan TYPING_TIMER_LENGTH = TimeSpan.FromMilliseconds(700); private enum ChatStates { Login, Chat } #region Fields /// <summary> /// The Socket.IO manager instance. /// </summary> private SocketManager Manager; /// <summary> /// Current state of the chat demo. /// </summary> private ChatStates State; /// <summary> /// The selected nickname /// </summary> private string userName = string.Empty; /// <summary> /// Currently typing message /// </summary> private string message = string.Empty; /// <summary> /// Sent and received messages. /// </summary> private string chatLog = string.Empty; /// <summary> /// Position of the scroller /// </summary> private Vector2 scrollPos; /// <summary> /// True if the user is currently typing /// </summary> private bool typing; /// <summary> /// When the message changed. /// </summary> private DateTime lastTypingTime = DateTime.MinValue; /// <summary> /// Users that typing. /// </summary> private List<string> typingUsers = new List<string>(); #endregion #region Unity Events void Start() { // The current state is Login State = ChatStates.Login; // Change an option to show how it should be done SocketOptions options = new SocketOptions(); options.AutoConnect = false; // Create the Socket.IO manager Manager = new SocketManager(new Uri("http://chat.socket.io/socket.io/"), options); // SaveLocal up custom chat events Manager.Socket.On("login", OnLogin); Manager.Socket.On("new message", OnNewMessage); Manager.Socket.On("user joined", OnUserJoined); Manager.Socket.On("user left", OnUserLeft); Manager.Socket.On("typing", OnTyping); Manager.Socket.On("stop typing", OnStopTyping); // The argument will be an Error object. Manager.Socket.On(SocketIOEventTypes.Error, (socket, packet, args) => Debug.LogError(string.Format("Error: {0}", args[0].ToString()))); // We set SocketOptions' AutoConnect to false, so we have to call it manually. Manager.Open(); } void OnDestroy() { // Leaving this sample, close the socket Manager.Close(); } void Update() { // Go back to the demo selector if (Input.GetKeyDown(KeyCode.Escape)) SampleSelector.SelectedSample.DestroyUnityObject(); // Stop typing if some time passed without typing if (typing) { var typingTimer = DateTime.UtcNow; var timeDiff = typingTimer - lastTypingTime; if (timeDiff >= TYPING_TIMER_LENGTH) { Manager.Socket.Emit("stop typing"); typing = false; } } } void OnGUI() { switch(State) { case ChatStates.Login: DrawLoginScreen(); break; case ChatStates.Chat: DrawChatScreen(); break; } } #endregion #region Chat Logic /// <summary> /// Called from an OnGUI event to draw the Login Screen. /// </summary> void DrawLoginScreen() { GUIHelper.DrawArea(GUIHelper.ClientArea, true, () => { GUILayout.BeginVertical(); GUILayout.FlexibleSpace(); GUIHelper.DrawCenteredText("What's your nickname?"); userName = GUILayout.TextField(userName); if (GUILayout.Button("Join")) SetUserName(); GUILayout.FlexibleSpace(); GUILayout.EndVertical(); }); } /// <summary> /// Called from an OnGUI event to draw the Chat Screen. /// </summary> void DrawChatScreen() { GUIHelper.DrawArea(GUIHelper.ClientArea, true, () => { GUILayout.BeginVertical(); scrollPos = GUILayout.BeginScrollView(scrollPos); GUILayout.Label(chatLog, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true)); GUILayout.EndScrollView(); string typing = string.Empty; if (typingUsers.Count > 0) { typing += string.Format("{0}", typingUsers[0]); for (int i = 1; i < typingUsers.Count; ++i) typing += string.Format(", {0}", typingUsers[i]); if (typingUsers.Count == 1) typing += " is typing!"; else typing += " are typing!"; } GUILayout.Label(typing); GUILayout.Label("Type here:"); GUILayout.BeginHorizontal(); message = GUILayout.TextField(message); if (GUILayout.Button("Send", GUILayout.MaxWidth(100))) SendMessage(); GUILayout.EndHorizontal(); if (GUI.changed) UpdateTyping(); GUILayout.EndVertical(); }); } void SetUserName() { if (string.IsNullOrEmpty(userName)) return; State = ChatStates.Chat; Manager.Socket.Emit("add user", userName); } void SendMessage() { if (string.IsNullOrEmpty(message)) return; Manager.Socket.Emit("new message", message); chatLog += string.Format("{0}: {1}\n", userName, message); message = string.Empty; } void UpdateTyping() { if (!typing) { typing = true; Manager.Socket.Emit("typing"); } lastTypingTime = DateTime.UtcNow; } void addParticipantsMessage(Dictionary<string, object> data) { int numUsers = Convert.ToInt32(data["numUsers"]); if (numUsers == 1) chatLog += "there's 1 participant\n"; else chatLog += "there are " + numUsers + " participants\n"; } void addChatMessage(Dictionary<string, object> data) { var username = data["username"] as string; var msg = data["message"] as string; chatLog += string.Format("{0}: {1}\n", username, msg); } void AddChatTyping(Dictionary<string, object> data) { var username = data["username"] as string; typingUsers.Add(username); } void RemoveChatTyping(Dictionary<string, object> data) { var username = data["username"] as string; int idx = typingUsers.FindIndex((name) => name.Equals(username)); if (idx != -1) typingUsers.RemoveAt(idx); } #endregion #region Custom SocketIO Events void OnLogin(Socket socket, Packet packet, params object[] args) { chatLog = "Welcome to Socket.IO Chat — \n"; addParticipantsMessage(args[0] as Dictionary<string, object>); } void OnNewMessage(Socket socket, Packet packet, params object[] args) { addChatMessage(args[0] as Dictionary<string, object>); } void OnUserJoined(Socket socket, Packet packet, params object[] args) { var data = args[0] as Dictionary<string, object>; var username = data["username"] as string; chatLog += string.Format("{0} joined\n", username); addParticipantsMessage(data); } void OnUserLeft(Socket socket, Packet packet, params object[] args) { var data = args[0] as Dictionary<string, object>; var username = data["username"] as string; chatLog += string.Format("{0} left\n", username); addParticipantsMessage(data); } void OnTyping(Socket socket, Packet packet, params object[] args) { AddChatTyping(args[0] as Dictionary<string, object>); } void OnStopTyping(Socket socket, Packet packet, params object[] args) { RemoveChatTyping(args[0] as Dictionary<string, object>); } #endregion }"; #endregion #region SocketIOWePlaySample public static string SocketIOWePlaySample = @"
using System; using System.Collections.Generic; using UnityEngine; using BestHTTP.SocketIO; using BestHTTP.SocketIO.Events; public sealed class SocketIOWePlaySample : MonoBehaviour { /// <summary> /// Possible states of the game. /// </summary> enum States { Connecting, WaitForNick, Joined } /// <summary> /// Controls that the server understands as a parameter in the move event. /// </summary> private string[] controls = new string[] { "left", "right", "a", "b", "up", "down", "select", "start" }; /// <summary> /// Ratio of the drawn GUI texture from the screen /// </summary> private const float ratio = 1.5f; /// <summary> /// How many messages to keep. /// </summary> private int MaxMessages = 50; /// <summary> /// Current state of the game. /// </summary> private States State; /// <summary> /// The root("/") Socket instance. /// </summary> private Socket Socket; /// <summary> /// The user-selected nickname. /// </summary> private string Nick = string.Empty; /// <summary> /// The message that the user want to send to the chat. /// </summary> private string messageToSend = string.Empty; /// <summary> /// How many user connected to the server. /// </summary> private int connections; /// <summary> /// Local and server sent messages. /// </summary> private List<string> messages = new List<string>(); /// <summary> /// The chat scroll position. /// </summary> private Vector2 scrollPos; /// <summary> /// The decoded texture from the server sent binary data /// </summary> private Texture2D FrameTexture; #region Unity Events void Start() { // Change an option to show how it should be done SocketOptions options = new SocketOptions(); options.AutoConnect = false; // Create the SocketManager instance var manager = new SocketManager(new Uri("http://io.weplay.io/socket.io/"), options); // Keep a reference to the root namespace Socket = manager.Socket; // SaveLocal up our event handlers. Socket.On(SocketIOEventTypes.Connect, OnConnected); Socket.On("joined", OnJoined); Socket.On("connections", OnConnections); Socket.On("join", OnJoin); Socket.On("move", OnMove); Socket.On("message", OnMessage); Socket.On("reload", OnReload); // Don't waste cpu cycles on decoding the payload, we are expecting only binary data with this event, // and we can access it through the packet's Attachments property. Socket.On("frame", OnFrame, /*autoDecodePayload:*/ false); // Add error handler, so we can display it Socket.On(SocketIOEventTypes.Error, OnError); // We set SocketOptions' AutoConnect to false, so we have to call it manually. manager.Open(); // We are connecting to the server. State = States.Connecting; } void OnDestroy() { // Leaving this sample, close the socket Socket.Manager.Close(); } void Update() { // Go back to the demo selector if (Input.GetKeyDown(KeyCode.Escape)) SampleSelector.SelectedSample.DestroyUnityObject(); } void OnGUI() { switch(State) { case States.Connecting: GUIHelper.DrawArea(GUIHelper.ClientArea, true, () => { GUILayout.BeginVertical(); GUILayout.FlexibleSpace(); GUIHelper.DrawCenteredText("Connecting to the server..."); GUILayout.FlexibleSpace(); GUILayout.EndVertical(); }); break; case States.WaitForNick: GUIHelper.DrawArea(GUIHelper.ClientArea, true, () => { DrawLoginScreen(); }); break; case States.Joined: GUIHelper.DrawArea(GUIHelper.ClientArea, true, () => { // Draw Texture if (FrameTexture != null) GUILayout.Box(FrameTexture); DrawControls(); DrawChat(); }); break; } } #endregion #region Helper Functions /// <summary> /// Called from an OnGUI event to draw the Login Screen. /// </summary> void DrawLoginScreen() { GUILayout.BeginVertical(); GUILayout.FlexibleSpace(); GUIHelper.DrawCenteredText("What's your nickname?"); Nick = GUILayout.TextField(Nick); if (GUILayout.Button("Join")) Join(); GUILayout.FlexibleSpace(); GUILayout.EndVertical(); } void DrawControls() { GUILayout.BeginHorizontal(); GUILayout.Label("Controls:"); for (int i = 0; i < controls.Length; ++i) if (GUILayout.Button(controls[i])) Socket.Emit("move", controls[i]); GUILayout.Label(" Connections: " + connections); GUILayout.EndHorizontal(); } void DrawChat(bool withInput = true) { GUILayout.BeginVertical(); // Draw the messages scrollPos = GUILayout.BeginScrollView(scrollPos, false, false); for (int i = 0; i < messages.Count; ++i) GUILayout.Label(messages[i], GUILayout.MinWidth(Screen.width)); GUILayout.EndScrollView(); if (withInput) { GUILayout.Label("Your message: "); GUILayout.BeginHorizontal(); messageToSend = GUILayout.TextField(messageToSend); if (GUILayout.Button("Send", GUILayout.MaxWidth(100))) SendMessage(); GUILayout.EndHorizontal(); } GUILayout.EndVertical(); } /// <summary> /// Add a message to the message log /// </summary> /// <param name="msg"></param> void AddMessage(string msg) { messages.Insert(0, msg); if (messages.Count > MaxMessages) messages.RemoveRange(MaxMessages, messages.Count - MaxMessages); } /// <summary> /// Send a chat message. The message must be in the messageToSend field. /// </summary> void SendMessage() { if (string.IsNullOrEmpty(messageToSend)) return; Socket.Emit("message", messageToSend); AddMessage(string.Format("{0}: {1}", Nick, messageToSend)); messageToSend = string.Empty; } /// <summary> /// Join to the game with the nickname stored in the Nick field. /// </summary> void Join() { PlayerPrefs.SetString("Nick", Nick); Socket.Emit("join", Nick); } /// <summary> /// Reload the game. /// </summary> void Reload() { FrameTexture = null; if (Socket != null) { Socket.Manager.Close(); Socket = null; Start(); } } #endregion #region SocketIO Events /// <summary> /// Socket connected event. /// </summary> private void OnConnected(Socket socket, Packet packet, params object[] args) { if (PlayerPrefs.HasKey("Nick")) { Nick = PlayerPrefs.GetString("Nick", "NickName"); Join(); } else State = States.WaitForNick; AddMessage("connected"); } /// <summary> /// Local player joined after sending a 'join' event /// </summary> private void OnJoined(Socket socket, Packet packet, params object[] args) { State = States.Joined; } /// <summary> /// Server sent us a 'reload' event. /// </summary> private void OnReload(Socket socket, Packet packet, params object[] args) { Reload(); } /// <summary> /// Someone wrote a message to the chat. /// </summary> private void OnMessage(Socket socket, Packet packet, params object[] args) { if (args.Length == 1) AddMessage(args[0] as string); else AddMessage(string.Format("{0}: {1}", args[1], args[0])); } /// <summary> /// Someone (including us) pressed a button. /// </summary> private void OnMove(Socket socket, Packet packet, params object[] args) { AddMessage(string.Format("{0} pressed {1}", args[1], args[0])); } /// <summary> /// Someone joined to the game /// </summary> private void OnJoin(Socket socket, Packet packet, params object[] args) { string loc = args.Length > 1 ? string.Format("({0})", args[1]) : string.Empty; AddMessage(string.Format("{0} joined {1}", args[0], loc)); } /// <summary> /// How many players are connected to the game. /// </summary> private void OnConnections(Socket socket, Packet packet, params object[] args) { connections = Convert.ToInt32(args[0]); } /// <summary> /// The server sent us a new picture to draw the game. /// </summary> private void OnFrame(Socket socket, Packet packet, params object[] args) { if (State != States.Joined) return; if (FrameTexture == null) { FrameTexture = new Texture2D(0, 0, TextureFormat.RGBA32, false); FrameTexture.filterMode = FilterMode.Point; } // Binary data usage case 1 - using directly the Attachments property: byte[] data = packet.Attachments[0]; // Binary data usage case 2 - using the packet's ReconstructAttachmentAsIndex() function /*packet.ReconstructAttachmentAsIndex(); args = packet.Decode(socket.Manager.Encoder); data = packet.Attachments[Convert.ToInt32(args[0])];*/ // Binary data usage case 3 - using the packet's ReconstructAttachmentAsBase64() function /*packet.ReconstructAttachmentAsBase64(); args = packet.Decode(socket.Manager.Encoder); data = Convert.FromBase64String(args[0] as string);*/ // Load the server sent picture FrameTexture.LoadImage(data); } /// <summary> /// Called on local or remote error. /// </summary> private void OnError(Socket socket, Packet packet, params object[] args) { AddMessage(string.Format("--ERROR - {0}", args[0].ToString())); } #endregion }"; #endregion #region SignalR SimpleStreamingSample public static string SignalR_SimpleStreamingSample = @"
using System; using UnityEngine; using BestHTTP.SignalR; sealed class SimpleStreamingSample : MonoBehaviour { readonly Uri URI = new Uri("http://besthttpsignalr.azurewebsites.net/streaming-connection"); /// <summary> /// Reference to the SignalR Connection /// </summary> Connection signalRConnection; /// <summary> /// Helper GUI class to handle and display a string-list /// </summary> GUIMessageList messages = new GUIMessageList(); #region Unity Events void Start() { // Create the SignalR connection signalRConnection = new Connection(URI); // set event handlers signalRConnection.OnNonHubMessage += signalRConnection_OnNonHubMessage; signalRConnection.OnStateChanged += signalRConnection_OnStateChanged; signalRConnection.OnError += signalRConnection_OnError; // Start connecting to the server signalRConnection.Open(); } void OnDestroy() { // Close the connection when the sample is closed signalRConnection.Close(); } void OnGUI() { GUIHelper.DrawArea(GUIHelper.ClientArea, true, () => { GUILayout.Label("Messages"); GUILayout.BeginHorizontal(); GUILayout.Space(20); messages.Draw(Screen.width - 20, 0); GUILayout.EndHorizontal(); }); } #endregion #region SignalR Events /// <summary> /// Handle Server-sent messages /// </summary> void signalRConnection_OnNonHubMessage(Connection connection, object data) { messages.Add("[Server Message] " + data.ToString()); } /// <summary> /// Display state changes /// </summary> void signalRConnection_OnStateChanged(Connection connection, ConnectionStates oldState, ConnectionStates newState) { messages.Add(string.Format("[State Change] {0} => {1}", oldState, newState)); } /// <summary> /// Display errors. /// </summary> void signalRConnection_OnError(Connection connection, string error) { messages.Add("[Error] " + error); } #endregion }"; #endregion #region SignalR ConnectionAPISample public static string SignalR_ConnectionAPISample = @"
using System; using System.Collections.Generic; using UnityEngine; using BestHTTP.SignalR; using BestHTTP.Cookies; public sealed class ConnectionAPISample : MonoBehaviour { readonly Uri URI = new Uri("http://besthttpsignalr.azurewebsites.net/raw-connection/"); /// <summary> /// Possible message types that the client can send to the server /// </summary> enum MessageTypes { Send, // 0 Broadcast, // 1 Join, // 2 PrivateMessage, // 3 AddToGroup, // 4 RemoveFromGroup, // 5 SendToGroup, // 6 BroadcastExceptMe, // 7 } #region Private Fields /// <summary> /// Reference to the SignalR Connection /// </summary> Connection signalRConnection; // Input strings string ToEveryBodyText = string.Empty; string ToMeText = string.Empty; string PrivateMessageText = string.Empty; string PrivateMessageUserOrGroupName = string.Empty; GUIMessageList messages = new GUIMessageList(); #endregion #region Unity Events void Start() { // SaveLocal a "user" cookie if we previously used the 'Enter Name' button. // The server will set this username to the new connection. if (PlayerPrefs.HasKey("userName")) CookieJar.SaveLocal(URI, new Cookie("user", PlayerPrefs.GetString("userName"))); signalRConnection = new Connection(URI); // to serialize the Message class, set a more advanced json encoder signalRConnection.JsonEncoder = new BestHTTP.SignalR.JsonEncoders.LitJsonEncoder(); // set up event handlers signalRConnection.OnStateChanged += signalRConnection_OnStateChanged; signalRConnection.OnNonHubMessage += signalRConnection_OnGeneralMessage; // Start to connect to the server. signalRConnection.Open(); } /// <summary> /// Draw the gui. /// Get input strings. /// Handle function calls. /// </summary> void OnGUI() { GUIHelper.DrawArea(GUIHelper.ClientArea, true, () => { GUILayout.BeginVertical(); #region To Everybody GUILayout.Label("To Everybody"); GUILayout.BeginHorizontal(); ToEveryBodyText = GUILayout.TextField(ToEveryBodyText, GUILayout.MinWidth(100)); if (GUILayout.Button("Broadcast")) Broadcast(ToEveryBodyText); if (GUILayout.Button("Broadcast (All Except Me)")) BroadcastExceptMe(ToEveryBodyText); if (GUILayout.Button("Enter Name")) EnterName(ToEveryBodyText); if (GUILayout.Button("Join Group")) JoinGroup(ToEveryBodyText); if (GUILayout.Button("Leave Group")) LeaveGroup(ToEveryBodyText); GUILayout.EndHorizontal(); #endregion #region To Me GUILayout.Label("To Me"); GUILayout.BeginHorizontal(); ToMeText = GUILayout.TextField(ToMeText, GUILayout.MinWidth(100)); if (GUILayout.Button("Send to me")) SendToMe(ToMeText); GUILayout.EndHorizontal(); #endregion #region Private Message GUILayout.Label("Private Message"); GUILayout.BeginHorizontal(); GUILayout.Label("Message:"); PrivateMessageText = GUILayout.TextField(PrivateMessageText, GUILayout.MinWidth(100)); GUILayout.Label("User or Group name:"); PrivateMessageUserOrGroupName = GUILayout.TextField(PrivateMessageUserOrGroupName, GUILayout.MinWidth(100)); if (GUILayout.Button("Send to user")) SendToUser(PrivateMessageUserOrGroupName, PrivateMessageText); if (GUILayout.Button("Send to group")) SendToGroup(PrivateMessageUserOrGroupName, PrivateMessageText); GUILayout.EndHorizontal(); #endregion GUILayout.Space(20); if (signalRConnection.State == ConnectionStates.Closed) { if (GUILayout.Button("Start Connection")) signalRConnection.Open(); } else if (GUILayout.Button("Stop Connection")) signalRConnection.Close(); GUILayout.Space(20); // Draw the messages GUILayout.Label("Messages"); GUILayout.BeginHorizontal(); GUILayout.Space(20); messages.Draw(Screen.width - 20, 0); GUILayout.EndHorizontal(); GUILayout.EndVertical(); }); } void OnDestroy() { // Close the connection when the sample is closed signalRConnection.Close(); } #endregion #region SignalR Events /// <summary> /// Handle non-hub messages /// </summary> void signalRConnection_OnGeneralMessage(Connection manager, object data) { // For now, just create a Json string from the sent data again string reencoded = BestHTTP.JSON.Json.Encode(data); // and display it messages.Add("[Server Message] " + reencoded); } void signalRConnection_OnStateChanged(Connection manager, ConnectionStates oldState, ConnectionStates newState) { // display state changes messages.Add(string.Format("[State Change] {0} => {1}", oldState.ToString(), newState.ToString())); } #endregion #region To EveryBody Functions /// <summary> /// Broadcast a message to all connected clients /// </summary> private void Broadcast(string text) { signalRConnection.Send(new { Type = MessageTypes.Broadcast, Value = text }); } /// <summary> /// Broadcast a message to all connected clients, except this client /// </summary> private void BroadcastExceptMe(string text) { signalRConnection.Send(new { Type = MessageTypes.BroadcastExceptMe, Value = text }); } /// <summary> /// SaveLocal a name for this connection. /// </summary> private void EnterName(string name) { signalRConnection.Send(new { Type = MessageTypes.Join, Value = name }); } /// <summary> /// Join to a group /// </summary> private void JoinGroup(string groupName) { signalRConnection.Send(new { Type = MessageTypes.AddToGroup, Value = groupName }); } /// <summary> /// Leave a group /// </summary> private void LeaveGroup(string groupName) { signalRConnection.Send(new { Type = MessageTypes.RemoveFromGroup, Value = groupName }); } #endregion #region To Me Functions /// <summary> /// Send a message to the very same client through the server /// </summary> void SendToMe(string text) { signalRConnection.Send(new { Type = MessageTypes.Send, Value = text }); } #endregion #region Private Message Functions /// <summary> /// Send a private message to a user /// </summary> void SendToUser(string userOrGroupName, string text) { signalRConnection.Send(new { Type = MessageTypes.PrivateMessage, Value = string.Format("{0}|{1}", userOrGroupName, text) }); } /// <summary> /// Send a message to a group /// </summary> void SendToGroup(string userOrGroupName, string text) { signalRConnection.Send(new { Type = MessageTypes.SendToGroup, Value = string.Format("{0}|{1}", userOrGroupName, text) }); } #endregion }"; #endregion #region SignalR ConnectionStatusSample public static string SignalR_ConnectionStatusSample = @"
using System; using System.Collections.Generic; using UnityEngine; using BestHTTP.SignalR; using BestHTTP.SignalR.Hubs; sealed class ConnectionStatusSample : MonoBehaviour { readonly Uri URI = new Uri("http://besthttpsignalr.azurewebsites.net/signalr"); /// <summary> /// Reference to the SignalR Connection /// </summary> Connection signalRConnection; GUIMessageList messages = new GUIMessageList(); #region Unity Events void Start() { // Connect to the StatusHub hub signalRConnection = new Connection(URI, "StatusHub"); // General events signalRConnection.OnNonHubMessage += signalRConnection_OnNonHubMessage; signalRConnection.OnError += signalRConnection_OnError; signalRConnection.OnStateChanged += signalRConnection_OnStateChanged; // SaveLocal up a Callback for Hub events signalRConnection["StatusHub"].OnMethodCall += statusHub_OnMethodCall; // Connect to the server signalRConnection.Open(); } void OnDestroy() { // Close the connection when we are closing the sample signalRConnection.Close(); } void OnGUI() { GUIHelper.DrawArea(GUIHelper.ClientArea, true, () => { GUILayout.BeginHorizontal(); if (GUILayout.Button("START") && signalRConnection.State != ConnectionStates.Connected) signalRConnection.Open(); if (GUILayout.Button("STOP") && signalRConnection.State == ConnectionStates.Connected) { signalRConnection.Close(); messages.Clear(); } if (GUILayout.Button("PING") && signalRConnection.State == ConnectionStates.Connected) { // Call a Hub-method on the server. signalRConnection["StatusHub"].Call("Ping"); } GUILayout.EndHorizontal(); GUILayout.Space(20); GUILayout.Label("Connection Status Messages"); GUILayout.BeginHorizontal(); GUILayout.Space(20); messages.Draw(Screen.width - 20, 0); GUILayout.EndHorizontal(); }); } #endregion #region SignalR Events /// <summary> /// Called on server-sent non-hub messages. /// </summary> void signalRConnection_OnNonHubMessage(Connection manager, object data) { messages.Add("[Server Message] " + data.ToString()); } /// <summary> /// Called when the SignalR Connection's state changes. /// </summary> void signalRConnection_OnStateChanged(Connection manager, ConnectionStates oldState, ConnectionStates newState) { messages.Add(string.Format("[State Change] {0} => {1}", oldState, newState)); } /// <summary> /// Called when an error occures. The plugin may close the connection after this event. /// </summary> void signalRConnection_OnError(Connection manager, string error) { messages.Add("[Error] " + error); } /// <summary> /// Called when the "StatusHub" hub wants to call a method on this client. /// </summary> void statusHub_OnMethodCall(Hub hub, string method, params object[] args) { string id = args.Length > 0 ? args[0] as string : string.Empty; string when = args.Length > 1 ? args[1].ToString() : string.Empty; switch (method) { case "joined": messages.Add(string.Format("[{0}] {1} joined at {2}", hub.Name, id, when)); break; case "rejoined": messages.Add(string.Format("[{0}] {1} reconnected at {2}", hub.Name, id, when)); break; case "leave": messages.Add(string.Format("[{0}] {1} leaved at {2}", hub.Name, id, when)); break; default: // pong messages.Add(string.Format("[{0}] {1}", hub.Name, method)); break; } } #endregion }"; #endregion #region SignalR DemoHubSample public static string SignalR_DemoHubSample = @"
using System; using UnityEngine; using BestHTTP.SignalR; using BestHTTP.SignalR.Hubs; using BestHTTP.SignalR.Messages; using BestHTTP.SignalR.JsonEncoders; class DemoHubSample : MonoBehaviour { readonly Uri URI = new Uri("http://besthttpsignalr.azurewebsites.net/signalr"); /// <summary> /// The SignalR connection instance /// </summary> Connection signalRConnection; /// <summary> /// DemoHub client side implementation /// </summary> DemoHub demoHub; /// <summary> /// TypedDemoHub client side implementation /// </summary> TypedDemoHub typedDemoHub; /// <summary> /// VB .NET Hub /// </summary> Hub vbDemoHub; /// <summary> /// Result of the VB demo's ReadStateValue call /// </summary> string vbReadStateResult = string.Empty; Vector2 scrollPos; void Start() { // Create the hubs demoHub = new DemoHub(); typedDemoHub = new TypedDemoHub(); vbDemoHub = new Hub("vbdemo"); // Create the SignalR connection, passing all the three hubs to it signalRConnection = new Connection(URI, demoHub, typedDemoHub, vbDemoHub); // Switch from the default encoder to the LitJson Encoder becouse it can handle the complex types too. signalRConnection.JsonEncoder = new LitJsonEncoder(); // Call the demo functions when we successfully connect to the server signalRConnection.OnConnected += (connection) => { var person = new { Name = "Foo", Age = 20, Address = new { Street = "One Microsoft Way", Zip = "98052" } }; // Call the demo functions demoHub.ReportProgress("Long running job!"); demoHub.AddToGroups(); demoHub.GetValue(); demoHub.TaskWithException(); demoHub.GenericTaskWithException(); demoHub.SynchronousException(); demoHub.DynamicTask(); demoHub.PassingDynamicComplex(person); demoHub.SimpleArray(new int[] { 5, 5, 6 }); demoHub.ComplexType(person); demoHub.ComplexArray(new object[] { person, person, person }); demoHub.Overload(); // set some state demoHub.State["name"] = "Testing state!"; demoHub.ReadStateValue(); demoHub.PlainTask(); demoHub.GenericTaskWithContinueWith(); typedDemoHub.Echo("Typed echo Callback"); // vbDemo is not wrapped in a hub class, it would contain only one function vbDemoHub.Call("readStateValue", (hub, msg, result) => vbReadStateResult = string.Format("Read some state from VB.NET! => {0}", result.ReturnValue == null ? "undefined" : result.ReturnValue.ToString())); }; // Start opening the signalR connection signalRConnection.Open(); } void OnDestroy() { // Close the connection when we are closing this sample signalRConnection.Close(); } void OnGUI() { GUIHelper.DrawArea(GUIHelper.ClientArea, true, () => { scrollPos = GUILayout.BeginScrollView(scrollPos, false, false); GUILayout.BeginVertical(); demoHub.Draw(); typedDemoHub.Draw(); GUILayout.Label("Read State Value"); GUILayout.BeginHorizontal(); GUILayout.Space(20); GUILayout.Label(vbReadStateResult); GUILayout.EndHorizontal(); GUILayout.Space(10); GUILayout.EndVertical(); GUILayout.EndScrollView(); }); } } /// <summary> /// Wrapper class of the 'TypedDemoHub' hub /// </summary> class TypedDemoHub : Hub { string typedEchoResult = string.Empty; string typedEchoClientResult = string.Empty; public TypedDemoHub() :base("typeddemohub") { } /// <summary> /// Called by the Connection class to be able to set up mappings. /// </summary> public override void Setup() { // Setup server-called functions base.On("Echo", Echo); } #region Server Called Functions /// <summary> /// Server-called, client side implementation of the Echo function /// </summary> private void Echo(Hub hub, MethodCallMessage methodCall) { typedEchoClientResult = string.Format("{0} #{1} triggered!", methodCall.Arguments[0], methodCall.Arguments[1]); } #endregion #region Client Called Function(s) /// <summary> /// Client-called, server side implementation of the Echo function. /// When the function successfully executed on the server the OnEcho_Done Callback function will be called. /// </summary> public void Echo(string msg) { base.Call("echo", OnEcho_Done, msg); } /// <summary> /// When the function successfully executed on the server this Callback function will be called. /// </summary> private void OnEcho_Done(Hub hub, ClientMessage originalMessage, ResultMessage result) { typedEchoResult = "TypedDemoHub.Echo(string message) invoked!"; } #endregion public void Draw() { GUILayout.Label("Typed Callback"); GUILayout.BeginHorizontal(); GUILayout.Space(20); GUILayout.BeginVertical(); GUILayout.Label(typedEchoResult); GUILayout.Label(typedEchoClientResult); GUILayout.EndVertical(); GUILayout.EndHorizontal(); GUILayout.Space(10); } } /// <summary> /// A wrapper class for the 'DemoHub' hub. /// </summary> class DemoHub : Hub { #region Private fields // These fields are here to store results of the function calls float longRunningJobProgress = 0f; string longRunningJobStatus = "Not Started!"; string fromArbitraryCodeResult = string.Empty; string groupAddedResult = string.Empty; string dynamicTaskResult = string.Empty; string genericTaskResult = string.Empty; string taskWithExceptionResult = string.Empty; string genericTaskWithExceptionResult = string.Empty; string synchronousExceptionResult = string.Empty; string invokingHubMethodWithDynamicResult = string.Empty; string simpleArrayResult = string.Empty; string complexTypeResult = string.Empty; string complexArrayResult = string.Empty; string voidOverloadResult = string.Empty; string intOverloadResult = string.Empty; string readStateResult = string.Empty; string plainTaskResult = string.Empty; string genericTaskWithContinueWithResult = string.Empty; GUIMessageList invokeResults = new GUIMessageList(); #endregion public DemoHub() : base("demo") { } /// <summary> /// Called by the Connection class to be able to set up mappings. /// </summary> public override void Setup() { // Setup server-called functions base.On("invoke", Invoke); base.On("signal", Signal); base.On("groupAdded", GroupAdded); base.On("fromArbitraryCode", FromArbitraryCode); } #region Client Called Functions #region ReportProgress public void ReportProgress(string arg) { Call("reportProgress", OnLongRunningJob_Done, null, OnLongRunningJob_Progress, arg); } public void OnLongRunningJob_Progress(Hub hub, ClientMessage originialMessage, ProgressMessage progress) { longRunningJobProgress = (float)progress.Progress; longRunningJobStatus = progress.Progress.ToString() + "%"; } public void OnLongRunningJob_Done(Hub hub, ClientMessage originalMessage, ResultMessage result) { longRunningJobStatus = result.ReturnValue.ToString(); MultipleCalls(); } #endregion public void MultipleCalls() { base.Call("multipleCalls"); } #region DynamicTask public void DynamicTask() { base.Call("dynamicTask", OnDynamicTask_Done, OnDynamicTask_Failed); } private void OnDynamicTask_Failed(Hub hub, ClientMessage originalMessage, ResultMessage result) { dynamicTaskResult = string.Format("The dynamic task failed :( {0}", result.ErrorMessage); } private void OnDynamicTask_Done(Hub hub, ClientMessage originalMessage, ResultMessage result) { dynamicTaskResult = string.Format("The dynamic task! {0}", result.ReturnValue); } #endregion public void AddToGroups() { base.Call("addToGroups"); } public void GetValue() { base.Call("getValue", (hub, msg, result) => genericTaskResult = string.Format("The value is {0} after 5 seconds", result.ReturnValue)); } public void TaskWithException() { base.Call("taskWithException", null, (hub, msg, result) => taskWithExceptionResult = string.Format("Error: {0}", result.ErrorMessage)); } public void GenericTaskWithException() { base.Call("genericTaskWithException", null, (hub, msg, result) => genericTaskWithExceptionResult = string.Format("Error: {0}", result.ErrorMessage)); } public void SynchronousException() { base.Call("synchronousException", null, (hub, msg, result) => synchronousExceptionResult = string.Format("Error: {0}", result.ErrorMessage)); } public void PassingDynamicComplex(object person) { base.Call("passingDynamicComplex", (hub, msg, result) => invokingHubMethodWithDynamicResult = string.Format("The person's age is {0}", result.ReturnValue), person); } public void SimpleArray(int[] array) { base.Call("simpleArray", (hub, msg, result) => simpleArrayResult = "Simple array works!", array); } public void ComplexType(object person) { base.Call("complexType", (hub, msg, result) => complexTypeResult = string.Format("Complex Type -> {0}", (this as IHub).Connection.JsonEncoder.Encode(this.State["person"])), person); } public void ComplexArray(object[] complexArray) { // We need to cast the object array to object to keep it as an array // http://stackoverflow.com/questions/36350/how-to-pass-a-single-object-to-a-params-object base.Call("ComplexArray", (hub, msg, result) => complexArrayResult = "Complex Array Works!", (object)complexArray); } #region Overloads public void Overload() { base.Call("Overload", OnVoidOverload_Done); } private void OnVoidOverload_Done(Hub hub, ClientMessage originalMessage, ResultMessage result) { voidOverloadResult = "Void Overload called"; Overload(101); } public void Overload(int number) { base.Call("Overload", OnIntOverload_Done, number); } private void OnIntOverload_Done(Hub hub, ClientMessage originalMessage, ResultMessage result) { intOverloadResult = string.Format("Overload with return value called => {0}", result.ReturnValue.ToString()); } #endregion public void ReadStateValue() { base.Call("readStateValue", (hub, msg, result) => readStateResult = string.Format("Read some state! => {0}", result.ReturnValue)); } public void PlainTask() { base.Call("plainTask", (hub, msg, result) => plainTaskResult = "Plain Task Result"); } public void GenericTaskWithContinueWith() { base.Call("genericTaskWithContinueWith", (hub, msg, result) => genericTaskWithContinueWithResult = result.ReturnValue.ToString()); } #endregion #region Server Called Functions private void FromArbitraryCode(Hub hub, MethodCallMessage methodCall) { fromArbitraryCodeResult = methodCall.Arguments[0] as string; } private void GroupAdded(Hub hub, MethodCallMessage methodCall) { if (!string.IsNullOrEmpty(groupAddedResult)) groupAddedResult = "Group Already Added!"; else groupAddedResult = "Group Added!"; } private void Signal(Hub hub, MethodCallMessage methodCall) { dynamicTaskResult = string.Format("The dynamic task! {0}", methodCall.Arguments[0]); } private void Invoke(Hub hub, MethodCallMessage methodCall) { invokeResults.Add(string.Format("{0} client state index -> {1}", methodCall.Arguments[0], this.State["index"])); } #endregion #region Draw /// <summary> /// Display the result's of the function calls. /// </summary> public void Draw() { GUILayout.Label("Arbitrary Code"); GUILayout.BeginHorizontal(); GUILayout.Space(20); GUILayout.Label(string.Format("Sending {0} from arbitrary code without the hub itself!", fromArbitraryCodeResult)); GUILayout.EndHorizontal(); GUILayout.Space(10); GUILayout.Label("Group Added"); GUILayout.BeginHorizontal(); GUILayout.Space(20); GUILayout.Label(groupAddedResult); GUILayout.EndHorizontal(); GUILayout.Space(10); GUILayout.Label("Dynamic Task"); GUILayout.BeginHorizontal(); GUILayout.Space(20); GUILayout.Label(dynamicTaskResult); GUILayout.EndHorizontal(); GUILayout.Space(10); GUILayout.Label("Report Progress"); GUILayout.BeginHorizontal(); GUILayout.Space(20); GUILayout.BeginVertical(); GUILayout.Label(longRunningJobStatus); GUILayout.HorizontalSlider(longRunningJobProgress, 0, 100); GUILayout.EndVertical(); GUILayout.EndHorizontal(); GUILayout.Space(10); GUILayout.Label("Generic Task"); GUILayout.BeginHorizontal(); GUILayout.Space(20); GUILayout.Label(genericTaskResult); GUILayout.EndHorizontal(); GUILayout.Space(10); GUILayout.Label("Task With Exception"); GUILayout.BeginHorizontal(); GUILayout.Space(20); GUILayout.Label(taskWithExceptionResult); GUILayout.EndHorizontal(); GUILayout.Space(10); GUILayout.Label("Generic Task With Exception"); GUILayout.BeginHorizontal(); GUILayout.Space(20); GUILayout.Label(genericTaskWithExceptionResult); GUILayout.EndHorizontal(); GUILayout.Space(10); GUILayout.Label("Synchronous Exception"); GUILayout.BeginHorizontal(); GUILayout.Space(20); GUILayout.Label(synchronousExceptionResult); GUILayout.EndHorizontal(); GUILayout.Space(10); GUILayout.Label("Invoking hub method with dynamic"); GUILayout.BeginHorizontal(); GUILayout.Space(20); GUILayout.Label(invokingHubMethodWithDynamicResult); GUILayout.EndHorizontal(); GUILayout.Space(10); GUILayout.Label("Simple Array"); GUILayout.BeginHorizontal(); GUILayout.Space(20); GUILayout.Label(simpleArrayResult); GUILayout.EndHorizontal(); GUILayout.Space(10); GUILayout.Label("Complex Type"); GUILayout.BeginHorizontal(); GUILayout.Space(20); GUILayout.Label(complexTypeResult); GUILayout.EndHorizontal(); GUILayout.Space(10); GUILayout.Label("Complex Array"); GUILayout.BeginHorizontal(); GUILayout.Space(20); GUILayout.Label(complexArrayResult); GUILayout.EndHorizontal(); GUILayout.Space(10); GUILayout.Label("Overloads"); GUILayout.BeginHorizontal(); GUILayout.Space(20); GUILayout.BeginVertical(); GUILayout.Label(voidOverloadResult); GUILayout.Label(intOverloadResult); GUILayout.EndVertical(); GUILayout.EndHorizontal(); GUILayout.Space(10); GUILayout.Label("Read State Value"); GUILayout.BeginHorizontal(); GUILayout.Space(20); GUILayout.Label(readStateResult); GUILayout.EndHorizontal(); GUILayout.Space(10); GUILayout.Label("Plain Task"); GUILayout.BeginHorizontal(); GUILayout.Space(20); GUILayout.Label(plainTaskResult); GUILayout.EndHorizontal(); GUILayout.Space(10); GUILayout.Label("Generic Task With ContinueWith"); GUILayout.BeginHorizontal(); GUILayout.Space(20); GUILayout.Label(genericTaskWithContinueWithResult); GUILayout.EndHorizontal(); GUILayout.Space(10); GUILayout.Label("Message Pump"); GUILayout.BeginHorizontal(); GUILayout.Space(20); invokeResults.Draw(Screen.width - 40, 270); GUILayout.EndHorizontal(); GUILayout.Space(10); } #endregion }"; #endregion #region SignalR AuthenticationSample public static string SignalR_AuthenticationSample = @"
using System; using System.Collections.Generic; using UnityEngine; using BestHTTP.SignalR; using BestHTTP.SignalR.Hubs; using BestHTTP.SignalR.Messages; using BestHTTP.SignalR.Authentication; class AuthenticationSample : MonoBehaviour { readonly Uri URI = new Uri("https://besthttpsignalr.azurewebsites.net/signalr"); #region Private Fields /// <summary> /// Reference to the SignalR Connection /// </summary> Connection signalRConnection; string userName = string.Empty; string role = string.Empty; Vector2 scrollPos; #endregion #region Unity Events void Start() { // Create the SignalR connection, and pass the hubs that we want to connect to signalRConnection = new Connection(URI, new BaseHub("noauthhub", "Messages"), new BaseHub("invokeauthhub", "Messages Invoked By Admin or Invoker"), new BaseHub("authhub", "Messages Requiring Authentication to Send or Receive"), new BaseHub("inheritauthhub", "Messages Requiring Authentication to Send or Receive Because of Inheritance"), new BaseHub("incomingauthhub", "Messages Requiring Authentication to Send"), new BaseHub("adminauthhub", "Messages Requiring Admin Membership to Send or Receive"), new BaseHub("userandroleauthhub", "Messages Requiring Name to be \"User\" and Role to be \"Admin\" to Send or Receive")); // SaveLocal the authenticator if we have valid fields if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(role)) signalRConnection.AuthenticationProvider = new HeaderAuthenticator(userName, role); // SaveLocal up event handler signalRConnection.OnConnected += signalRConnection_OnConnected; // Start to connect to the server. signalRConnection.Open(); } void OnDestroy() { // Close the connection when we are closing the sample signalRConnection.Close(); } void OnGUI() { GUIHelper.DrawArea(GUIHelper.ClientArea, true, () => { scrollPos = GUILayout.BeginScrollView(scrollPos, false, false); GUILayout.BeginVertical(); if (signalRConnection.AuthenticationProvider == null) { GUILayout.BeginHorizontal(); GUILayout.Label("Username (Enter 'User'):"); userName = GUILayout.TextField(userName, GUILayout.MinWidth(100)); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); GUILayout.Label("Roles (Enter 'Invoker' or 'Admin'):"); role = GUILayout.TextField(role, GUILayout.MinWidth(100)); GUILayout.EndHorizontal(); if (GUILayout.Button("Log in")) Restart(); } for (int i = 0; i < signalRConnection.Hubs.Length; ++i) (signalRConnection.Hubs[i] as BaseHub).Draw(); GUILayout.EndVertical(); GUILayout.EndScrollView(); }); } #endregion /// <summary> /// Called when we successfully connected to the server. /// </summary> void signalRConnection_OnConnected(Connection manager) { // call 'InvokedFromClient' on all hubs for (int i = 0; i < signalRConnection.Hubs.Length; ++i) (signalRConnection.Hubs[i] as BaseHub).InvokedFromClient(); } /// <summary> /// Helper function to do a hard-restart to the server. /// </summary> void Restart() { // Clean up signalRConnection.OnConnected -= signalRConnection_OnConnected; // Close current connection signalRConnection.Close(); signalRConnection = null; // start again, with authentication if we filled in all input fields Start(); } } /// <summary> /// Hub implementation for the authentication demo. All hubs that we connect to has the same server and client side functions. /// </summary> class BaseHub : Hub { #region Private Fields /// <summary> /// Hub specific title /// </summary> private string Title; private GUIMessageList messages = new GUIMessageList(); #endregion public BaseHub(string name, string title) : base(name) { this.Title = title; } /// <summary> /// Called by the Connection class to be able to set up mappings. /// </summary> public override void Setup() { // Map the server-callable method names to the real functions. On("joined", Joined); On("rejoined", Rejoined); On("left", Left); On("invoked", Invoked); } #region Server Called Functions private void Joined(Hub hub, MethodCallMessage methodCall) { Dictionary<string, object> AuthInfo = methodCall.Arguments[2] as Dictionary<string, object>; messages.Add(string.Format("{0} joined at {1}\n\tIsAuthenticated: {2} IsAdmin: {3} UserName: {4}", methodCall.Arguments[0], methodCall.Arguments[1], AuthInfo["IsAuthenticated"], AuthInfo["IsAdmin"], AuthInfo["UserName"])); } private void Rejoined(Hub hub, MethodCallMessage methodCall) { messages.Add(string.Format("{0} reconnected at {1}", methodCall.Arguments[0], methodCall.Arguments[1])); } private void Left(Hub hub, MethodCallMessage methodCall) { messages.Add(string.Format("{0} left at {1}", methodCall.Arguments[0], methodCall.Arguments[1])); } private void Invoked(Hub hub, MethodCallMessage methodCall) { messages.Add(string.Format("{0} invoked hub method at {1}", methodCall.Arguments[0], methodCall.Arguments[1])); } #endregion #region Client callable function implementation public void InvokedFromClient() { base.Call("invokedFromClient", OnInvoked, OnInvokeFailed); } private void OnInvoked(Hub hub, ClientMessage originalMessage, ResultMessage result) { Debug.Log(hub.Name + " invokedFromClient success!"); } /// <summary> /// This Callback function will be called every time we try to access a protected API while we are using an non-authenticated connection. /// </summary> private void OnInvokeFailed(Hub hub, ClientMessage originalMessage, ResultMessage result) { Debug.LogWarning(hub.Name + " " + result.ErrorMessage); } #endregion public void Draw() { GUILayout.Label(this.Title); GUILayout.BeginHorizontal(); GUILayout.Space(20); messages.Draw(Screen.width - 20, 100); GUILayout.EndHorizontal(); } }"; #endregion #region CacheMaintenanceSample public static string CacheMaintenanceSample = @"
using System; using System.Collections.Generic; using UnityEngine; using BestHTTP; using BestHTTP.Caching; public sealed class CacheMaintenanceSample : MonoBehaviour { /// <summary> /// An enum for better readability /// </summary> enum DeleteOlderTypes { Days, Hours, Mins, Secs }; #region Private Fields /// <summary> /// What methode to call on the TimeSpan /// </summary> DeleteOlderTypes deleteOlderType = DeleteOlderTypes.Secs; /// <summary> /// The value for the TimeSpan. /// </summary> int value = 10; /// <summary> /// What's our maximum cache size /// </summary> int maxCacheSize = 5 * 1024 * 1024; #endregion #region Unity Events void OnGUI() { GUIHelper.DrawArea(GUIHelper.ClientArea, true, () => { GUILayout.BeginHorizontal(); GUILayout.Label("Delete cached entities older then"); GUILayout.Label(value.ToString(), GUILayout.MinWidth(50)); value = (int)GUILayout.HorizontalSlider(value, 1, 60, GUILayout.MinWidth(100)); GUILayout.Space(10); deleteOlderType = (DeleteOlderTypes)(int)GUILayout.SelectionGrid((int)deleteOlderType, new string[] { "Days", "Hours", "Mins", "Secs" }, 4); GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); GUILayout.Space(10); GUILayout.BeginHorizontal(); GUILayout.Label("Max Cache Size (bytes): ", GUILayout.Width(150)); GUILayout.Label(maxCacheSize.ToString("N0"), GUILayout.Width(70)); maxCacheSize = (int)GUILayout.HorizontalSlider(maxCacheSize, 1024, 10 * 1024 * 1024); GUILayout.EndHorizontal(); GUILayout.Space(10); if (GUILayout.Button("Maintenance")) { TimeSpan deleteOlder = TimeSpan.FromDays(14); switch (deleteOlderType) { case DeleteOlderTypes.Days: deleteOlder = TimeSpan.FromDays(value); break; case DeleteOlderTypes.Hours: deleteOlder = TimeSpan.FromHours(value); break; case DeleteOlderTypes.Mins: deleteOlder = TimeSpan.FromMinutes(value); break; case DeleteOlderTypes.Secs: deleteOlder = TimeSpan.FromSeconds(value); break; } // Call the BeginMaintainence function. It will run on a thread to do not block the main thread. HTTPCacheService.BeginMaintainence(new HTTPCacheMaintananceParams(deleteOlder, (ulong)maxCacheSize)); } }); } #endregion }"; #endregion } }