diff --git a/AssemblyInfo.cs b/AssemblyInfo.cs new file mode 100644 index 0000000..dd86131 --- /dev/null +++ b/AssemblyInfo.cs @@ -0,0 +1,6 @@ +using System.Runtime.InteropServices; + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] \ No newline at end of file diff --git a/Async/Async.cs b/Async/Async.cs index 7946f62..7edb461 100644 --- a/Async/Async.cs +++ b/Async/Async.cs @@ -1,7 +1,8 @@ using System; using System.Collections.Generic; -namespace Wizcorp.MageSDK.Utils { +namespace Wizcorp.MageSDK.Utils +{ /// /// Async is a utility class which provides straight-forward, powerful functions for working with asynchronous C#. /// @@ -9,26 +10,31 @@ namespace Wizcorp.MageSDK.Utils { /// some common patterns for asynchronous control flow (parallel, series, waterfall…). All these functions assume you follow /// the convention of providing a single callback as the last argument of your async function. /// - public class Async { - public static void each(List items, Action> fn, Action cb) { - if (items == null || items.Count == 0) { - cb(null); + public static class Async + { + public static void Each(List items, Action> action, Action callback) + { + if (items == null || items.Count == 0) + { + callback(null); return; } - int currentItemI = 0; + var currentItemI = 0; Action iterate = null; iterate = () => { - if (currentItemI >= items.Count) { - cb(null); + if (currentItemI >= items.Count) + { + callback(null); return; } // Execute the given function on this item - fn(items[currentItemI], (Exception error) => { + action(items[currentItemI], error => { // Stop iteration if there was an error - if (error != null) { - cb(error); + if (error != null) + { + callback(error); return; } @@ -42,34 +48,38 @@ public static void each(List items, Action> fn, Actio iterate(); } - public static void series(List>> actionItems, Action cb) { - bool isEmpty = actionItems == null || actionItems.Count == 0; - if (isEmpty) { - cb(null); + public static void Series(List>> actions, Action callback) + { + bool isEmpty = actions == null || actions.Count == 0; + if (isEmpty) + { + callback(null); return; } - int currentItemI = 0; + var currentActionI = 0; Action iterate = null; iterate = () => { - if (currentItemI >= actionItems.Count) { - cb(null); + if (currentActionI >= actions.Count) + { + callback(null); return; } // Shift an element from the list - Action> actionItem = actionItems[currentItemI]; + Action> action = actions[currentActionI]; // Execute the given function on this item - actionItem((Exception error) => { + action(error => { // Stop iteration if there was an error - if (error != null) { - cb(error); + if (error != null) + { + callback(error); return; } // Continue to next item - currentItemI++; + currentActionI++; iterate(); }); }; diff --git a/EventEmitter/EventEmitter.cs b/EventEmitter/EventEmitter.cs index dacbc57..8db7f0a 100644 --- a/EventEmitter/EventEmitter.cs +++ b/EventEmitter/EventEmitter.cs @@ -2,15 +2,19 @@ using System.Collections.Generic; using System.ComponentModel; -namespace Wizcorp.MageSDK.Event { - public class EventEmitter { +namespace Wizcorp.MageSDK.Event +{ + public class EventEmitter + { // private Dictionary eventTags = new Dictionary(); private EventHandlerList eventsList = new EventHandlerList(); // - public void on(string eventTag, Action handler) { - if (!eventTags.ContainsKey(eventTag)) { + public void On(string eventTag, Action handler) + { + if (!eventTags.ContainsKey(eventTag)) + { eventTags.Add(eventTag, new object()); } @@ -18,37 +22,51 @@ public void on(string eventTag, Action handler) { } // - public void once(string eventTag, Action handler) { + public void Once(string eventTag, Action handler) + { Action handlerWrapper = null; - handlerWrapper = (object obj, T arguments) => { + handlerWrapper = (obj, arguments) => { eventsList.RemoveHandler(eventTags[eventTag], handlerWrapper); handler(obj, arguments); }; - on(eventTag, handlerWrapper); + On(eventTag, handlerWrapper); } // - public void emit(string eventTag, object sender, T arguments) { - if (!eventTags.ContainsKey(eventTag)) { + public void Emit(string eventTag, object sender, T arguments) + { + if (!eventTags.ContainsKey(eventTag)) + { return; } - Action execEventList = (Action)eventsList[eventTags[eventTag]]; - execEventList(sender, arguments); + var execEventList = (Action)eventsList[eventTags[eventTag]]; + if (execEventList != null) + { + execEventList(sender, arguments); + } } - public void emit(string eventTag, T arguments) { - emit(eventTag, null, arguments); + public void Emit(string eventTag, T arguments) + { + Emit(eventTag, null, arguments); } // - public void off(string eventTag, Action handler) { + public void Off(string eventTag, Action handler) + { + if (!eventTags.ContainsKey(eventTag)) + { + return; + } + eventsList.RemoveHandler(eventTags[eventTag], handler); } // - public void removeAllListeners() { + public void RemoveAllListeners() + { // Destroy all event handlers eventsList.Dispose(); eventsList = new EventHandlerList(); diff --git a/HTTPRequest/HTTPRequest.DotNet.cs b/HTTPRequest/HTTPRequest.DotNet.cs index 085f3a2..4f69be7 100644 --- a/HTTPRequest/HTTPRequest.DotNet.cs +++ b/HTTPRequest/HTTPRequest.DotNet.cs @@ -10,8 +10,10 @@ using System.Text; using System.Threading; -namespace Wizcorp.MageSDK.Network.Http { - public class HTTPRequest { +namespace Wizcorp.MageSDK.Network.Http +{ + public class HttpRequest + { private HttpWebRequest request; private CookieContainer cookies; private Action cb; @@ -19,11 +21,14 @@ public class HTTPRequest { // Timeout setting for request private long _timeout = 100 * 1000; - public long timeout { - get { + public long timeout + { + get + { return _timeout; } - set { + set + { _timeout = value; timeoutTimer.Dispose(); @@ -36,7 +41,8 @@ public long timeout { // Constructor - public HTTPRequest(string url, string contentType, byte[] postData, Dictionary headers, CookieContainer cookies, Action cb) { + public HttpRequest(string url, string contentType, byte[] postData, Dictionary headers, CookieContainer cookies, Action cb) + { // Start timeout timer timeoutTimer = new Timer((object state) => { this.Abort(); @@ -48,19 +54,23 @@ public HTTPRequest(string url, string contentType, byte[] postData, Dictionary entry in headers) { + if (headers != null) + { + foreach (KeyValuePair entry in headers) + { httpRequest.Headers.Add(entry.Key, entry.Value); } } // Set content type if provided - if (contentType != null) { + if (contentType != null) + { httpRequest.ContentType = contentType; } // Set cookies if provided - if (cookies != null) { + if (cookies != null) + { httpRequest.CookieContainer = cookies; } @@ -70,12 +80,16 @@ public HTTPRequest(string url, string contentType, byte[] postData, Dictionary { - if (requestError != null) { + if (requestError != null) + { cb(requestError, null); return; } @@ -89,13 +103,17 @@ public HTTPRequest(string url, string contentType, byte[] postData, Dictionary cb) { + private void WritePostData(byte[] postData, Action cb) + { request.BeginGetRequestStream((IAsyncResult callbackResult) => { - try { + try + { Stream postStream = request.EndGetRequestStream(callbackResult); postStream.Write(postData, 0, postData.Length); postStream.Close(); - } catch (Exception error) { + } + catch (Exception error) + { cb(error); return; } @@ -104,7 +122,8 @@ private void WritePostData(byte[] postData, Action cb) { } // Read response data from request buffer - private void ReadResponseData(Action cb) { + private void ReadResponseData(Action cb) + { // Begin waiting for a response request.BeginGetResponse(new AsyncCallback((IAsyncResult callbackResult) => { // Cleanup timeout @@ -113,15 +132,19 @@ private void ReadResponseData(Action cb) { // Process response string responseString = null; - try { + try + { HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(callbackResult); - using (StreamReader httpWebStreamReader = new StreamReader(response.GetResponseStream())) { + using (StreamReader httpWebStreamReader = new StreamReader(response.GetResponseStream())) + { responseString = httpWebStreamReader.ReadToEnd(); } response.Close(); - } catch (Exception error) { + } + catch (Exception error) + { cb(error, null); return; } @@ -132,8 +155,10 @@ private void ReadResponseData(Action cb) { // Abort request - public void Abort() { - if (request == null) { + public void Abort() + { + if (request == null) + { return; } @@ -147,21 +172,24 @@ public void Abort() { // Create GET request and return it - public static HTTPRequest Get(string url, Dictionary headers, CookieContainer cookies, Action cb) { + public static HttpRequest Get(string url, Dictionary headers, CookieContainer cookies, Action cb) + { // Create request and return it // The callback will be called when the request is complete - return new HTTPRequest(url, null, null, headers, cookies, cb); + return new HttpRequest(url, null, null, headers, cookies, cb); } // Create POST request and return it - public static HTTPRequest Post(string url, string contentType, string postData, Dictionary headers, CookieContainer cookies, Action cb) { + public static HttpRequest Post(string url, string contentType, string postData, Dictionary headers, CookieContainer cookies, Action cb) + { byte[] binaryPostData = Encoding.UTF8.GetBytes(postData); return Post(url, contentType, binaryPostData, headers, cookies, cb); } // Create POST request and return it - public static HTTPRequest Post(string url, string contentType, byte[] postData, Dictionary headers, CookieContainer cookies, Action cb) { - return new HTTPRequest(url, contentType, postData, headers, cookies, cb); + public static HttpRequest Post(string url, string contentType, byte[] postData, Dictionary headers, CookieContainer cookies, Action cb) + { + return new HttpRequest(url, contentType, postData, headers, cookies, cb); } } } diff --git a/HTTPRequest/HTTPRequest.Unity.cs b/HTTPRequest/HTTPRequest.Unity.cs index b9293f7..7703b34 100644 --- a/HTTPRequest/HTTPRequest.Unity.cs +++ b/HTTPRequest/HTTPRequest.Unity.cs @@ -12,50 +12,48 @@ using UnityEngine; -namespace Wizcorp.MageSDK.Network.Http { - public class HTTPRequest { +namespace Wizcorp.MageSDK.Network.Http +{ + public class HttpRequest + { private WWW request; private CookieContainer cookies; private Action cb; - private Stopwatch timeoutTimer; // Timeout setting for request - private long _timeout = 100 * 1000; - public long timeout { - get { - return _timeout; - } - set { - _timeout = value; - } - } + public long Timeout = 100 * 1000; + private Stopwatch timeoutTimer = new Stopwatch(); // Constructor - public HTTPRequest(string url, string contentType, byte[] postData, Dictionary headers, CookieContainer cookies, Action cb) { + public HttpRequest(string url, string contentType, byte[] postData, Dictionary headers, CookieContainer cookies, Action cb) + { // Start timeout timer - timeoutTimer = new Stopwatch(); timeoutTimer.Start(); // Queue constructor for main thread execution - HTTPRequestManager.Queue(Constructor(url, contentType, postData, headers, cookies, cb)); + HttpRequestManager.Queue(Constructor(url, contentType, postData, headers, cookies, cb)); } // Main thread constructor - private IEnumerator Constructor(string url, string contentType, byte[] postData, Dictionary headers, CookieContainer cookies, Action cb) { - Dictionary headersCopy = new Dictionary(headers); + private IEnumerator Constructor(string url, string contentType, byte[] postData, Dictionary headers, CookieContainer cookies, Action cb) + { + Dictionary headersCopy = (headers != null) ? new Dictionary(headers) : new Dictionary(); // Set content type if provided - if (contentType != null) { + if (contentType != null) + { headersCopy.Add("ContentType", contentType); } // Set cookies if provided - if (cookies != null) { + if (cookies != null) + { Uri requestUri = new Uri(url); string cookieString = cookies.GetCookieHeader(requestUri); - if (!string.IsNullOrEmpty(cookieString)) { + if (!string.IsNullOrEmpty(cookieString)) + { headersCopy.Add("Cookie", cookieString); } } @@ -63,20 +61,23 @@ private IEnumerator Constructor(string url, string contentType, byte[] postData, // Setup private properties and fire off the request this.cb = cb; this.cookies = cookies; - this.request = new WWW(url, postData, headersCopy); + request = new WWW(url, postData, headersCopy); // Initiate response - HTTPRequestManager.Queue(WaitLoop()); + HttpRequestManager.Queue(WaitLoop()); yield break; } // Wait for www request to complete with timeout checks - private IEnumerator WaitLoop() { - while (request != null && !request.isDone) { - if (timeoutTimer.ElapsedMilliseconds >= timeout) { + private IEnumerator WaitLoop() + { + while (request != null && !request.isDone) + { + if (timeoutTimer.ElapsedMilliseconds >= Timeout) + { // Timed out abort the request with timeout error - this.Abort(); + Abort(); cb(new Exception("Request timed out"), null); yield break; } @@ -86,7 +87,8 @@ private IEnumerator WaitLoop() { } // Check if we destroyed the request due to an abort - if (request == null) { + if (request == null) + { yield break; } @@ -95,18 +97,21 @@ private IEnumerator WaitLoop() { timeoutTimer = null; // Check if there is a callback - if (cb == null) { + if (cb == null) + { yield break; } // Check if there was an error with the request - if (request.error != null) { - int statusCode = 0; - if (request.responseHeaders.ContainsKey("STATUS")) { + if (request.error != null) + { + var statusCode = 0; + if (request.responseHeaders.ContainsKey("STATUS")) + { statusCode = int.Parse(request.responseHeaders["STATUS"].Split(' ')[1]); } - cb(new HTTPRequestException(request.error, statusCode), null); + cb(new HttpRequestException(request.error, statusCode), null); yield break; } @@ -119,12 +124,15 @@ private IEnumerator WaitLoop() { Uri requestUri = new Uri(request.url); PropertyInfo pinfoHeadersString = typeof(WWW).GetProperty("responseHeadersString", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); - if (pinfoHeadersString != null) { + if (pinfoHeadersString != null) + { string headersString = pinfoHeadersString.GetValue(request, null) as string; string[] headerLines = headersString.Split('\n'); - foreach (string headerStr in headerLines) { - if (headerStr.StartsWith("set-cookie:", true, null)) { + foreach (string headerStr in headerLines) + { + if (headerStr.StartsWith("set-cookie:", true, null)) + { cookies.SetCookies(requestUri, headerStr.Remove(0, 11)); } } @@ -135,8 +143,10 @@ private IEnumerator WaitLoop() { // Abort request - public void Abort() { - if (this.request == null) { + public void Abort() + { + if (this.request == null) + { return; } @@ -150,22 +160,30 @@ public void Abort() { // Create GET request and return it - public static HTTPRequest Get(string url, Dictionary headers, CookieContainer cookies, Action cb) { + public static HttpRequest Get(string url, Dictionary headers, CookieContainer cookies, Action cb) + { // Create request and return it // The callback will be called when the request is complete - return new HTTPRequest(url, null, null, headers, cookies, cb); + return new HttpRequest(url, null, null, headers, cookies, cb); } // Create POST request and return it - public static HTTPRequest Post(string url, string contentType, string postData, Dictionary headers, CookieContainer cookies, Action cb) { + public static HttpRequest Post( + string url, string contentType, string postData, Dictionary headers, CookieContainer cookies, + Action cb) + { byte[] binaryPostData = Encoding.UTF8.GetBytes(postData); return Post(url, contentType, binaryPostData, headers, cookies, cb); } // Create POST request and return it - public static HTTPRequest Post(string url, string contentType, byte[] postData, Dictionary headers, CookieContainer cookies, Action cb) { - return new HTTPRequest(url, contentType, postData, headers, cookies, cb); + public static HttpRequest Post( + string url, string contentType, byte[] postData, Dictionary headers, CookieContainer cookies, + Action cb) + { + return new HttpRequest(url, contentType, postData, headers, cookies, cb); } } } + #endif diff --git a/HTTPRequest/HTTPRequestException.cs b/HTTPRequest/HTTPRequestException.cs index dda517e..c32e272 100644 --- a/HTTPRequest/HTTPRequestException.cs +++ b/HTTPRequest/HTTPRequestException.cs @@ -1,11 +1,14 @@ using System; -namespace Wizcorp.MageSDK.Network.Http { - public class HTTPRequestException : Exception { - public int Status = 0; +namespace Wizcorp.MageSDK.Network.Http +{ + public class HttpRequestException : Exception + { + public int Status; - public HTTPRequestException(string Message, int Status) : base(Message) { - this.Status = Status; + public HttpRequestException(string message, int status) : base(message) + { + Status = status; } } } diff --git a/HTTPRequest/HTTPRequestManager.cs b/HTTPRequest/HTTPRequestManager.cs index 4ad2c4d..fe8649e 100644 --- a/HTTPRequest/HTTPRequestManager.cs +++ b/HTTPRequest/HTTPRequestManager.cs @@ -3,22 +3,29 @@ using Wizcorp.MageSDK.Utils; -namespace Wizcorp.MageSDK.Network.Http { - public class HTTPRequestManager : MonoSingleton { +namespace Wizcorp.MageSDK.Network.Http +{ + public class HttpRequestManager : MonoSingleton + { // private static List queued = new List(); // - public static void Queue(IEnumerator coroutine) { - lock ((object)queued) { + public static void Queue(IEnumerator coroutine) + { + lock ((object)queued) + { queued.Add(coroutine); } } // - void Update() { - lock ((object)queued) { - for (int i = 0; i < queued.Count; i += 1) { + void Update() + { + lock ((object)queued) + { + for (var i = 0; i < queued.Count; i += 1) + { StartCoroutine(queued[i]); } diff --git a/JSONRPC/JSONRPC.cs b/JSONRPC/JSONRPC.cs index f6497a4..0ef0a22 100644 --- a/JSONRPC/JSONRPC.cs +++ b/JSONRPC/JSONRPC.cs @@ -1,39 +1,44 @@ using System; using System.Collections.Generic; using System.Net; -using System.IO; -using System.Text; using Newtonsoft.Json.Linq; using Wizcorp.MageSDK.Network.Http; -namespace Wizcorp.MageSDK.Network.JsonRpc { - public class JSONRPC { +namespace Wizcorp.MageSDK.Network.JsonRpc +{ + public class JsonRpc + { // Endpoint and Basic Authentication private string endpoint; - Dictionary headers; + private Dictionary headers; - public void SetEndpoint(string endpoint, Dictionary headers = null) { + public void SetEndpoint(string endpoint, Dictionary headers = null) + { this.endpoint = endpoint; this.headers = new Dictionary(headers); } - public void Call(string methodName, JObject parameters, Dictionary headers, CookieContainer cookies, Action cb) { + public void Call(string methodName, JObject parameters, Dictionary headers, CookieContainer cookies, Action cb) + { Call(JValue.CreateNull(), methodName, parameters, headers, cookies, cb); } - public void Call(string id, string methodName, JObject parameters, Dictionary headers, CookieContainer cookies, Action cb) { + public void Call(string id, string methodName, JObject parameters, Dictionary headers, CookieContainer cookies, Action cb) + { Call(new JValue(id), methodName, parameters, headers, cookies, cb); } - public void Call(int id, string methodName, JObject parameters, Dictionary headers, CookieContainer cookies, Action cb) { + public void Call(int id, string methodName, JObject parameters, Dictionary headers, CookieContainer cookies, Action cb) + { Call(new JValue(id), methodName, parameters, headers, cookies, cb); } - public void Call(JValue id, string methodName, JObject parameters, Dictionary headers, CookieContainer cookies, Action cb) { + public void Call(JValue id, string methodName, JObject parameters, Dictionary headers, CookieContainer cookies, Action cb) + { // Setup JSON request object - JObject requestObject = new JObject(); + var requestObject = new JObject(); requestObject.Add("jsonrpc", new JValue("2.0")); requestObject.Add("id", id); @@ -42,25 +47,32 @@ public void Call(JValue id, string methodName, JObject parameters, Dictionary { - if (requestError != null) { + SendRequest(postData, headers, cookies, (requestError, responseString) => { + if (requestError != null) + { cb(requestError, null); return; } // Deserialize the JSON response JObject responseObject; - try { + try + { responseObject = JObject.Parse(responseString); - } catch (Exception parseError) { + } + catch (Exception parseError) + { cb(parseError, null); return; } @@ -69,28 +81,36 @@ public void Call(JValue id, string methodName, JObject parameters, Dictionary headers, CookieContainer cookies, Action cb) { + public void CallBatch(JsonRpcBatch rpcBatch, Dictionary headers, CookieContainer cookies, Action cb) + { // Serialize JSON request object into string string postData; - try { - postData = rpcBatch.batch.ToString(); - } catch (Exception serializeError) { + try + { + postData = rpcBatch.Batch.ToString(); + } + catch (Exception serializeError) + { cb(serializeError, null); return; } // Send request - SendRequest(postData, headers, cookies, (Exception requestError, string responseString) => { - if (requestError != null) { + SendRequest(postData, headers, cookies, (requestError, responseString) => { + if (requestError != null) + { cb(requestError, null); return; } // Deserialize the JSON response JArray responseArray; - try { + try + { responseArray = JArray.Parse(responseString); - } catch (Exception parseError) { + } + catch (Exception parseError) + { cb(parseError, null); return; } @@ -99,17 +119,21 @@ public void CallBatch(JSONRPCBatch rpcBatch, Dictionary headers, }); } - private void SendRequest(string postData, Dictionary headers, CookieContainer cookies, Action cb) { + private void SendRequest(string postData, Dictionary headers, CookieContainer cookies, Action cb) + { // Make sure the endpoint is set - if (string.IsNullOrEmpty(this.endpoint)) { + if (string.IsNullOrEmpty(endpoint)) + { cb(new Exception("Endpoint has not been set"), null); return; } // Make a copy of the provided headers and add additional required headers Dictionary finalHeaders = new Dictionary(this.headers); - foreach (var header in headers) { - if (finalHeaders.ContainsKey(header.Key)) { + foreach (var header in headers) + { + if (finalHeaders.ContainsKey(header.Key)) + { continue; } @@ -117,7 +141,7 @@ private void SendRequest(string postData, Dictionary headers, Co } // Send HTTP post to JSON rpc endpoint - HTTPRequest.Post(this.endpoint, "application/json", postData, finalHeaders, cookies, cb); + HttpRequest.Post(endpoint, "application/json", postData, finalHeaders, cookies, cb); } } } diff --git a/JSONRPC/JSONRPCBatch.cs b/JSONRPC/JSONRPCBatch.cs index 1b74c17..682e6cf 100644 --- a/JSONRPC/JSONRPCBatch.cs +++ b/JSONRPC/JSONRPCBatch.cs @@ -1,30 +1,36 @@ using Newtonsoft.Json.Linq; -namespace Wizcorp.MageSDK.Network.JsonRpc { - public class JSONRPCBatch { - public JArray batch = new JArray(); +namespace Wizcorp.MageSDK.Network.JsonRpc +{ + public class JsonRpcBatch + { + public JArray Batch = new JArray(); - public void Add(string methodName, JObject parameters) { + public void Add(string methodName, JObject parameters) + { Add(JValue.CreateNull(), methodName, parameters); } - public void Add(string id, string methodName, JObject parameters) { + public void Add(string id, string methodName, JObject parameters) + { Add(new JValue(id), methodName, parameters); } - public void Add(int id, string methodName, JObject parameters) { + public void Add(int id, string methodName, JObject parameters) + { Add(new JValue(id), methodName, parameters); } - public void Add(JValue id, string methodName, JObject parameters) { - JObject requestObject = new JObject(); + public void Add(JValue id, string methodName, JObject parameters) + { + var requestObject = new JObject(); requestObject.Add("jsonrpc", new JValue("2.0")); requestObject.Add("id", id); requestObject.Add("method", new JValue(methodName)); requestObject.Add("params", parameters); - batch.Add(requestObject); + Batch.Add(requestObject); } } } diff --git a/Mage/Archivist/Archivist.cs b/Mage/Archivist/Archivist.cs index 8f13ba1..7eb47c0 100644 --- a/Mage/Archivist/Archivist.cs +++ b/Mage/Archivist/Archivist.cs @@ -6,48 +6,58 @@ using Wizcorp.MageSDK.Event; using Wizcorp.MageSDK.Log; -namespace Wizcorp.MageSDK.MageClient { - public class Archivist : EventEmitter { - private Mage mage { get { return Mage.Instance; } } - private Logger logger { get { return mage.logger("archivist"); } } +namespace Wizcorp.MageSDK.MageClient +{ + public class Archivist : EventEmitter + { + private Mage Mage + { + get { return Mage.Instance; } + } + + private Logger Logger + { + get { return Mage.Logger("Archivist"); } + } // Local cache of all retrieved vault values - private Dictionary _cache = new Dictionary(); + private Dictionary cache = new Dictionary(); // Constructor - public Archivist() { + public Archivist() + { // Set data to vault value when set event received - mage.eventManager.on("archivist:set", (object sender, JToken info) => { - string topic = (string)info["key"]["topic"]; - JObject index = (JObject)info["key"]["index"]; + Mage.EventManager.On("archivist:set", (sender, info) => { + var topic = (string)info["key"]["topic"]; + var index = (JObject)info["key"]["index"]; JToken data = info["value"]["data"]; - string mediaType = (string)info["value"]["mediaType"]; - int? expirationTime = (int?)info["expirationTime"]; + var mediaType = (string)info["value"]["mediaType"]; + var expirationTime = (int?)info["expirationTime"]; ValueSet(topic, index, data, mediaType, expirationTime); }); // Del data inside vault value when del event received - mage.eventManager.on("archivist:del", (object sender, JToken info) => { - string topic = (string)info["key"]["topic"]; - JObject index = (JObject)info["key"]["index"]; + Mage.EventManager.On("archivist:del", (sender, info) => { + var topic = (string)info["key"]["topic"]; + var index = (JObject)info["key"]["index"]; ValueDel(topic, index); }); // Touch vault value expiry when touch event received - mage.eventManager.on("archivist:touch", (object sender, JToken info) => { - string topic = (string)info["key"]["topic"]; - JObject index = (JObject)info["key"]["index"]; - int? expirationTime = (int?)info["expirationTime"]; + Mage.EventManager.On("archivist:touch", (sender, info) => { + var topic = (string)info["key"]["topic"]; + var index = (JObject)info["key"]["index"]; + var expirationTime = (int?)info["expirationTime"]; ValueTouch(topic, index, expirationTime); }); // Apply changes to vault value when applyDiff event is received - mage.eventManager.on("archivist:applyDiff", (object sender, JToken info) => { - string topic = (string)info["key"]["topic"]; - JObject index = (JObject)info["key"]["index"]; - JArray diff = (JArray)info["diff"]; - int? expirationTime = (int?)info["expirationTime"]; + Mage.EventManager.On("archivist:applyDiff", (sender, info) => { + var topic = (string)info["key"]["topic"]; + var index = (JObject)info["key"]["index"]; + var diff = (JArray)info["diff"]; + var expirationTime = (int?)info["expirationTime"]; ValueApplyDiff(topic, index, diff, expirationTime); }); } @@ -58,20 +68,23 @@ public Archivist() { //////////////////////////////////////////// // Returns string id of a vault value for given topic and index - private static string CreateCacheKey(string topic, JObject index) { + private static string CreateCacheKey(string topic, JObject index) + { // Sort the keys so order of index is always the same - List indexKeys = new List(); - foreach (var property in index) { + var indexKeys = new List(); + foreach (KeyValuePair property in index) + { indexKeys.Add(property.Key); } indexKeys.Sort(); // Construct cache key list with correct ordering - List cacheKeys = new List(); + var cacheKeys = new List(); cacheKeys.Add(topic); - foreach (string indexKey in indexKeys) { - cacheKeys.Add(indexKey + "=" + index[indexKey].ToString()); + foreach (string indexKey in indexKeys) + { + cacheKeys.Add(indexKey + "=" + index[indexKey]); } // Join the cache key list into final key string @@ -80,15 +93,19 @@ private static string CreateCacheKey(string topic, JObject index) { // Returns cache value if it exists and has not passed max allowed age - private VaultValue GetCacheValue(string cacheKeyName, int? maxAge = null) { - lock ((object)_cache) { - if (!_cache.ContainsKey(cacheKeyName)) { + private VaultValue GetCacheValue(string cacheKeyName, int? maxAge = null) + { + lock ((object)cache) + { + if (!cache.ContainsKey(cacheKeyName)) + { return null; } - VaultValue value = _cache[cacheKeyName]; - double timespan = (DateTime.UtcNow - value.writtenAt).TotalMilliseconds; - if (maxAge != null && timespan > maxAge * 1000) { + VaultValue value = cache[cacheKeyName]; + double timespan = (DateTime.UtcNow - value.WrittenAt).TotalMilliseconds; + if (maxAge != null && timespan > maxAge * 1000) + { return null; } @@ -98,34 +115,41 @@ private VaultValue GetCacheValue(string cacheKeyName, int? maxAge = null) { // Return cache dictionary - public Dictionary GetCache() { - return _cache; + public Dictionary GetCache() + { + return cache; } // Clear out the cache entirely - public void ClearCache() { - lock ((object)_cache) { - _cache.Clear(); + public void ClearCache() + { + lock ((object)cache) + { + cache.Clear(); } } // Remove a vault value from the cache by it's topic and index - public void DeleteCacheItem(string topic, JObject index) { + public void DeleteCacheItem(string topic, JObject index) + { DeleteCacheItem(CreateCacheKey(topic, index)); } // Remove a vault value from the cache by it's cache key name - public void DeleteCacheItem(string cacheKeyName) { - lock ((object)_cache) { - logger.debug("Deleting cache item: " + cacheKeyName); - if (!_cache.ContainsKey(cacheKeyName)) { + public void DeleteCacheItem(string cacheKeyName) + { + lock ((object)cache) + { + Logger.Debug("Deleting cache item: " + cacheKeyName); + if (!cache.ContainsKey(cacheKeyName)) + { return; } - _cache.Remove(cacheKeyName); + cache.Remove(cacheKeyName); } } @@ -133,31 +157,40 @@ public void DeleteCacheItem(string cacheKeyName) { //////////////////////////////////////////// // Vault Value Manipulation // //////////////////////////////////////////// - private void ValueSetOrDelete(JObject info) { - string topic = (string)info["key"]["topic"]; - JObject index = (JObject)info["key"]["index"]; - JObject rawValue = (JObject)info["value"]; - - if (rawValue != null) { + private void ValueSetOrDelete(JObject info) + { + var topic = (string)info["key"]["topic"]; + var index = (JObject)info["key"]["index"]; + var rawValue = (JObject)info["value"]; + + if (rawValue != null) + { ValueSet(topic, index, rawValue["data"], (string)rawValue["mediaType"], (int?)info["expirationTime"]); - } else { + } + else + { ValueDel(topic, index); } } - private void ValueSet(string topic, JObject index, JToken data, string mediaType, int? expirationTime) { + private void ValueSet(string topic, JObject index, JToken data, string mediaType, int? expirationTime) + { string cacheKeyName = CreateCacheKey(topic, index); - VaultValue cacheValue = null; + VaultValue cacheValue; // NOTE: even though some of these operations lock already, we put them inside this // lock to ensure there is no time inconsistencies if things happen too fast. - lock ((object)_cache) { + lock ((object)cache) + { cacheValue = GetCacheValue(cacheKeyName); - if (cacheValue == null) { + if (cacheValue == null) + { // If it doesn't exist, create a new vault value cacheValue = new VaultValue(topic, index); - _cache.Add(cacheKeyName, cacheValue); - } else { + cache.Add(cacheKeyName, cacheValue); + } + else + { // If it exists delete existing value in preparation for set cacheValue.Del(); } @@ -168,26 +201,29 @@ private void ValueSet(string topic, JObject index, JToken data, string mediaType } // Emit set event - this.emit(topic + ":set", cacheValue); + Emit(topic + ":set", cacheValue); } - private void ValueAdd(string topic, JObject index, JToken data, string mediaType, int? expirationTime) { + private void ValueAdd(string topic, JObject index, JToken data, string mediaType, int? expirationTime) + { string cacheKeyName = CreateCacheKey(topic, index); - VaultValue cacheValue = null; + VaultValue cacheValue; // NOTE: even though some of these operations lock already, we put them inside this // lock to ensure there is no time inconsistencies if things happen too fast. - lock ((object)_cache) { + lock ((object)cache) + { // Check if value already exists cacheValue = GetCacheValue(cacheKeyName); - if (cacheValue != null) { - logger.error("Could not add value (already exists): " + cacheKeyName); + if (cacheValue != null) + { + Logger.Error("Could not add value (already exists): " + cacheKeyName); return; } // Create new vault value cacheValue = new VaultValue(topic, index); - _cache.Add(cacheKeyName, cacheValue); + cache.Add(cacheKeyName, cacheValue); // Set data to vault value cacheValue.SetData(mediaType, data); @@ -195,15 +231,17 @@ private void ValueAdd(string topic, JObject index, JToken data, string mediaType } // Emit add event - this.emit(topic + ":add", cacheValue); + Emit(topic + ":add", cacheValue); } - private void ValueDel(string topic, JObject index) { + private void ValueDel(string topic, JObject index) + { // Check if value already exists string cacheKeyName = CreateCacheKey(topic, index); VaultValue cacheValue = GetCacheValue(cacheKeyName); - if (cacheValue == null) { - logger.warning("Could not delete value (doesn't exist): " + cacheKeyName); + if (cacheValue == null) + { + Logger.Warning("Could not delete value (doesn't exist): " + cacheKeyName); return; } @@ -211,15 +249,17 @@ private void ValueDel(string topic, JObject index) { cacheValue.Del(); // Emit touch event - this.emit(topic + ":del", cacheValue); + Emit(topic + ":del", cacheValue); } - private void ValueTouch(string topic, JObject index, int? expirationTime) { + private void ValueTouch(string topic, JObject index, int? expirationTime) + { // Check if value already exists string cacheKeyName = CreateCacheKey(topic, index); VaultValue cacheValue = GetCacheValue(cacheKeyName); - if (cacheValue == null) { - logger.warning("Could not touch value (doesn't exist): " + cacheKeyName); + if (cacheValue == null) + { + Logger.Warning("Could not touch value (doesn't exist): " + cacheKeyName); return; } @@ -227,15 +267,17 @@ private void ValueTouch(string topic, JObject index, int? expirationTime) { cacheValue.Touch(expirationTime); // Emit touch event - this.emit(topic + ":touch", cacheValue); + Emit(topic + ":touch", cacheValue); } - private void ValueApplyDiff(string topic, JObject index, JArray diff, int? expirationTime) { + private void ValueApplyDiff(string topic, JObject index, JArray diff, int? expirationTime) + { // Make sure value exists string cacheKeyName = CreateCacheKey(topic, index); VaultValue cacheValue = GetCacheValue(cacheKeyName); - if (cacheValue == null) { - logger.warning("Got a diff for a non-existent value:" + cacheKeyName); + if (cacheValue == null) + { + Logger.Warning("Got a diff for a non-existent value:" + cacheKeyName); return; } @@ -244,40 +286,44 @@ private void ValueApplyDiff(string topic, JObject index, JArray diff, int? expir cacheValue.Touch(expirationTime); // Emit applyDiff event - this.emit(topic + ":applyDiff", cacheValue); + Emit(topic + ":applyDiff", cacheValue); } //////////////////////////////////////////// // Raw Communication // //////////////////////////////////////////// - private void rawGet(string topic, JObject index, Action cb) { - JObject parameters = new JObject(); + private void RawGet(string topic, JObject index, Action cb) + { + var parameters = new JObject(); parameters.Add("topic", topic); parameters.Add("index", index); - mage.commandCenter.SendCommand("archivist.rawGet", parameters, cb); + Mage.CommandCenter.SendCommand("archivist.rawGet", parameters, cb); } - private void rawMGet(JToken queries, JObject options, Action cb) { - JObject parameters = new JObject(); + private void RawMGet(JToken queries, JObject options, Action cb) + { + var parameters = new JObject(); parameters.Add(new JProperty("queries", queries)); parameters.Add("options", options); - mage.commandCenter.SendCommand("archivist.rawMGet", parameters, cb); + Mage.CommandCenter.SendCommand("archivist.rawMGet", parameters, cb); } - private void rawList(string topic, JObject partialIndex, JObject options, Action cb) { - JObject parameters = new JObject(); + private void RawList(string topic, JObject partialIndex, JObject options, Action cb) + { + var parameters = new JObject(); parameters.Add("topic", new JValue(topic)); parameters.Add("partialIndex", partialIndex); parameters.Add("options", options); - mage.commandCenter.SendCommand("archivist.rawList", parameters, cb); + Mage.CommandCenter.SendCommand("archivist.rawList", parameters, cb); } - private void rawSet(string topic, JObject index, JToken data, string mediaType, string encoding, string expirationTime, Action cb) { - JObject parameters = new JObject(); + private void RawSet(string topic, JObject index, JToken data, string mediaType, string encoding, string expirationTime, Action cb) + { + var parameters = new JObject(); parameters.Add("topic", new JValue(topic)); parameters.Add("index", index); parameters.Add(new JProperty("data", data)); @@ -285,25 +331,28 @@ private void rawSet(string topic, JObject index, JToken data, string mediaType, parameters.Add("encoding", new JValue(encoding)); parameters.Add("expirationTime", new JValue(expirationTime)); - mage.commandCenter.SendCommand("archivist.rawSet", parameters, cb); + Mage.CommandCenter.SendCommand("archivist.rawSet", parameters, cb); } - private void rawDel(string topic, JObject index, Action cb) { - JObject parameters = new JObject(); + private void RawDel(string topic, JObject index, Action cb) + { + var parameters = new JObject(); parameters.Add("topic", new JValue(topic)); parameters.Add("index", index); - mage.commandCenter.SendCommand("archivist.rawDel", parameters, cb); + Mage.CommandCenter.SendCommand("archivist.rawDel", parameters, cb); } //////////////////////////////////////////// // Exposed Operations // //////////////////////////////////////////// - public void get(string topic, JObject index, JObject options, Action cb) { + public void Get(string topic, JObject index, JObject options, Action cb) + { // Default options options = (options != null) ? options : new JObject(); - if (options["optional"] == null) { + if (options["optional"] == null) + { options.Add("optional", new JValue(false)); } @@ -311,55 +360,66 @@ public void get(string topic, JObject index, JObject options, Action { - if (error != null) { + RawGet(topic, index, (error, result) => { + if (error != null) + { cb(error, null); return; } // Parse value - try { + try + { ValueSetOrDelete((JObject)result); - } catch (Exception cacheError) { + } + catch (Exception cacheError) + { cb(cacheError, null); return; } // Return result - cb(null, GetCacheValue(cacheKeyName).data); + cb(null, GetCacheValue(cacheKeyName).Data); }); } - public void mget(JArray queries, JObject options, Action cb) { + public void MGet(JArray queries, JObject options, Action cb) + { // Default options options = (options != null) ? options : new JObject(); - if (options["optional"] == null) { + if (options["optional"] == null) + { options.Add("optional", new JValue(false)); } // Keep track of actual data we need from server - JArray realQueries = new JArray(); - Dictionary realQueryKeys = new Dictionary(); - JArray responseArray = new JArray(); + var realQueries = new JArray(); + var realQueryKeys = new Dictionary(); + var responseArray = new JArray(); // Check cache - foreach (JObject query in queries) { - string topic = (string)query["topic"]; - JObject index = (JObject)query["index"]; + foreach (JObject query in queries) + { + var topic = (string)query["topic"]; + var index = (JObject)query["index"]; string cacheKeyName = CreateCacheKey(topic, index); VaultValue cacheValue = GetCacheValue(cacheKeyName, (int?)options["maxAge"]); - if (cacheValue != null) { - responseArray.Add(cacheValue.data); - } else { + if (cacheValue != null) + { + responseArray.Add(cacheValue.Data); + } + else + { realQueryKeys.Add(cacheKeyName, responseArray.Count); responseArray.Add(null); realQueries.Add(query); @@ -368,24 +428,34 @@ public void mget(JArray queries, JObject options, Action cb) // Check if any real queries exist - if (realQueries.Count == 0) { + if (realQueries.Count == 0) + { cb(null, responseArray); return; } // Get data from server - rawMGet(realQueries, options, (Exception error, JToken results) => { - if (error != null) { + RawMGet(realQueries, options, (error, results) => { + if (error != null) + { cb(error, null); return; } - try { - foreach (JObject topicValue in results as JArray) { + try + { + var resultsArray = results as JArray; + if (resultsArray == null) + { + throw new Exception("RawMGet returned non Array results: " + results); + } + + foreach (JObject topicValue in resultsArray) + { // Determine value cacheKeyName - string topic = (string)topicValue["key"]["topic"]; - JObject index = (JObject)topicValue["key"]["index"]; + var topic = (string)topicValue["key"]["topic"]; + var index = (JObject)topicValue["key"]["index"]; string cacheKeyName = CreateCacheKey(topic, index); // Set value to cache @@ -393,9 +463,11 @@ public void mget(JArray queries, JObject options, Action cb) // Add value to response int responseKey = realQueryKeys[cacheKeyName]; - responseArray[responseKey].Replace(GetCacheValue(cacheKeyName).data); + responseArray[responseKey].Replace(GetCacheValue(cacheKeyName).Data); } - } catch (Exception cacheError) { + } + catch (Exception cacheError) + { cb(cacheError, null); return; } @@ -405,27 +477,33 @@ public void mget(JArray queries, JObject options, Action cb) }); } - public void mget(JObject queries, JObject options, Action cb) { + public void MGet(JObject queries, JObject options, Action cb) + { // Default options options = (options != null) ? options : new JObject(); - if (options["optional"] == null) { + if (options["optional"] == null) + { options.Add("optional", new JValue(false)); } // Keep track of actual data we need from server - JObject realQueries = new JObject(); - Dictionary realQueryKeys = new Dictionary(); - JObject responseObject = new JObject(); + var realQueries = new JObject(); + var realQueryKeys = new Dictionary(); + var responseObject = new JObject(); // Check cache - foreach (var query in queries) { + foreach (KeyValuePair query in queries) + { string cacheKeyName = CreateCacheKey(query.Value["topic"].ToString(), query.Value["index"] as JObject); VaultValue cacheValue = GetCacheValue(cacheKeyName, (int?)options["maxAge"]); - if (cacheValue != null) { - responseObject.Add(query.Key, cacheValue.data); - } else { + if (cacheValue != null) + { + responseObject.Add(query.Key, cacheValue.Data); + } + else + { realQueryKeys.Add(cacheKeyName, query.Key); realQueries.Add(query.Key, query.Value); } @@ -433,24 +511,34 @@ public void mget(JObject queries, JObject options, Action cb) // Check if any real queries exist - if (realQueries.Count == 0) { + if (realQueries.Count == 0) + { cb(null, responseObject); return; } // Get data from server - rawMGet(realQueries, options, (Exception error, JToken results) => { - if (error != null) { + RawMGet(realQueries, options, (error, results) => { + if (error != null) + { cb(error, null); return; } - try { - foreach (JObject topicValue in results as JArray) { + try + { + var resultsArray = results as JArray; + if (resultsArray == null) + { + throw new Exception("RawMGet returned non Array results: " + results); + } + + foreach (JObject topicValue in resultsArray) + { // Determine value cacheKeyName string valueTopic = topicValue["key"]["topic"].ToString(); - JObject valueIndex = (JObject)topicValue["key"]["index"]; + var valueIndex = (JObject)topicValue["key"]["index"]; string cacheKeyName = CreateCacheKey(valueTopic, valueIndex); // Set value to cache @@ -458,9 +546,11 @@ public void mget(JObject queries, JObject options, Action cb) // Add value to response string responseKey = realQueryKeys[cacheKeyName]; - responseObject.Add(responseKey, GetCacheValue(cacheKeyName).data); + responseObject.Add(responseKey, GetCacheValue(cacheKeyName).Data); } - } catch (Exception cacheError) { + } + catch (Exception cacheError) + { cb(cacheError, null); return; } @@ -470,8 +560,9 @@ public void mget(JObject queries, JObject options, Action cb) }); } - public void list(string topic, JObject partialIndex, JObject options, Action cb) { - rawList(topic, partialIndex, options, cb); + public void List(string topic, JObject partialIndex, JObject options, Action cb) + { + RawList(topic, partialIndex, options, cb); } } } diff --git a/Mage/Archivist/VaultValue.cs b/Mage/Archivist/VaultValue.cs index aca67c5..d4f7410 100644 --- a/Mage/Archivist/VaultValue.cs +++ b/Mage/Archivist/VaultValue.cs @@ -4,92 +4,88 @@ using Wizcorp.MageSDK.Tomes; -namespace Wizcorp.MageSDK.MageClient { - public class VaultValue { +namespace Wizcorp.MageSDK.MageClient +{ + public class VaultValue + { // - private string _topic; - public string topic { get { return _topic; } } - - private JObject _index; - public JObject index { get { return _index; } } - - private JToken _data; - public JToken data { get { return _data; } } - - private string _mediaType; - public string mediaType { get { return _mediaType; } } - - private int? _expirationTime; - public int? expirationTime { get { return _expirationTime; } } + public string Topic { get; private set; } + public JObject Index { get; private set; } + public JToken Data { get; private set; } + public string MediaType { get; private set; } + public int? ExpirationTime { get; private set; } + public DateTime WrittenAt { get; private set; } // - private DateTime _writtenAt; - public DateTime writtenAt { get { return _writtenAt; } } - - - // - public VaultValue(string topic, JObject index) { - _topic = topic; - _index = index; + public VaultValue(string topic, JObject index) + { + Topic = topic; + Index = index; } - // TODO: implement multiple media-types and encoding - public void SetData(string mediaType, JToken data) { - lock ((object)this) { + public void SetData(string mediaType, JToken data) + { + lock ((object)this) + { // Detect media type - _mediaType = mediaType; + MediaType = mediaType; // Set data based on media type - _data = Tome.Conjure(JToken.Parse((string)data)); + Data = Tome.Conjure(JToken.Parse((string)data)); // Bump the last written time - _writtenAt = DateTime.UtcNow; + WrittenAt = DateTime.UtcNow; } } - // - public void Del() { - lock ((object)this) { + public void Del() + { + lock ((object)this) + { // Bump the last written time and check if we have data to destroy - _writtenAt = DateTime.UtcNow; - if (_data == null) { + WrittenAt = DateTime.UtcNow; + if (Data == null) + { return; } // Cleanup data - Tome.Destroy(_data); - _data = null; - _mediaType = null; + Tome.Destroy(Data); + Data = null; + MediaType = null; // Clear expiration time Touch(null); } } - // TODO: the actual implementation of this requires the MAGE time module, // also we have a timer to clear the value once expired. - public void Touch(int? expirationTime) { - lock ((object)this) { - _expirationTime = expirationTime; + public void Touch(int? expirationTime) + { + lock ((object)this) + { + ExpirationTime = expirationTime; } } - // - public void ApplyDiff(JArray diff) { - lock ((object)this) { - if (diff == null || _data == null) { + public void ApplyDiff(JArray diff) + { + lock ((object)this) + { + if (diff == null || Data == null) + { return; } // Apply diff to data - Tome.ApplyDiff(_data, diff); + Tome.ApplyDiff(Data, diff); // Bump the last written time - _writtenAt = DateTime.UtcNow; + WrittenAt = DateTime.UtcNow; } } } diff --git a/Mage/CommandCenter/CommandBatch.cs b/Mage/CommandCenter/CommandBatch.cs index 716a691..db67fd8 100644 --- a/Mage/CommandCenter/CommandBatch.cs +++ b/Mage/CommandCenter/CommandBatch.cs @@ -3,20 +3,24 @@ using Newtonsoft.Json.Linq; -namespace Wizcorp.MageSDK.MageClient.Command { - public class CommandBatch { - public int queryId; - public List> batchHeaders = new List>(); - public List batchItems = new List(); +namespace Wizcorp.MageSDK.MageClient.Command +{ + public class CommandBatch + { + public int QueryId; + public List> BatchHeaders = new List>(); + public List BatchItems = new List(); - public object serialisedCache; + public Object SerialisedCache; - public CommandBatch(int queryId) { - this.queryId = queryId; + public CommandBatch(int queryId) + { + QueryId = queryId; } - public void Queue(string commandName, JObject parameters, Action cb) { - batchItems.Add(new CommandBatchItem(commandName, parameters, cb)); + public void Queue(string commandName, JObject parameters, Action cb) + { + BatchItems.Add(new CommandBatchItem(commandName, parameters, cb)); } } } diff --git a/Mage/CommandCenter/CommandBatchItem.cs b/Mage/CommandCenter/CommandBatchItem.cs index 97ce042..7b3358b 100644 --- a/Mage/CommandCenter/CommandBatchItem.cs +++ b/Mage/CommandCenter/CommandBatchItem.cs @@ -2,16 +2,19 @@ using Newtonsoft.Json.Linq; -namespace Wizcorp.MageSDK.MageClient.Command { - public class CommandBatchItem { - public string commandName; - public JObject parameters; - public Action cb; +namespace Wizcorp.MageSDK.MageClient.Command +{ + public class CommandBatchItem + { + public string CommandName; + public JObject Parameters; + public Action Cb; - public CommandBatchItem(string commandName, JObject parameters, Action cb) { - this.commandName = commandName; - this.parameters = parameters; - this.cb = cb; + public CommandBatchItem(string commandName, JObject parameters, Action cb) + { + CommandName = commandName; + Parameters = parameters; + Cb = cb; } } } diff --git a/Mage/CommandCenter/CommandCenter.cs b/Mage/CommandCenter/CommandCenter.cs index 609f143..fd0b18e 100644 --- a/Mage/CommandCenter/CommandCenter.cs +++ b/Mage/CommandCenter/CommandCenter.cs @@ -7,15 +7,24 @@ using Wizcorp.MageSDK.CommandCenter.Client; using Wizcorp.MageSDK.Log; -namespace Wizcorp.MageSDK.MageClient.Command { - public class CommandCenter { - private Mage mage { get { return Mage.Instance; } } - private Logger logger { get { return mage.logger("CommandCenter"); } } +namespace Wizcorp.MageSDK.MageClient.Command +{ + public class CommandCenter + { + private Mage Mage + { + get { return Mage.Instance; } + } + + private Logger Logger + { + get { return Mage.Logger("CommandCenter"); } + } // Endpoint and credentials private string baseUrl; private string appName; - Dictionary headers = new Dictionary(); + private Dictionary headers = new Dictionary(); // Message Hooks public delegate void MessageHook(CommandBatch commandBatch); @@ -31,26 +40,31 @@ public class CommandCenter { private CommandBatch sendingBatch; // - public CommandCenter(CommandTransportType transportType = CommandTransportType.HTTP) { + public CommandCenter(CommandTransportType transportType = CommandTransportType.HTTP) + { currentBatch = new CommandBatch(nextQueryId++); SetTransport(transportType); } // - public void SetTransport(CommandTransportType transportType) { + public void SetTransport(CommandTransportType transportType) + { // Cleanup existing transport client - if (transportClient != null) { - transportClient = null; - } + transportClient = null; // Create new transport client instance - if (transportType == CommandTransportType.HTTP) { - transportClient = new CommandHTTPClient() as CommandTransportClient; + if (transportType == CommandTransportType.HTTP) + { + transportClient = new CommandHttpClient(); transportClient.SetEndpoint(baseUrl, appName, headers); - } else if (transportType == CommandTransportType.JSONRPC) { - transportClient = new CommandJSONRPCClient() as CommandTransportClient; + } + else if (transportType == CommandTransportType.JSONRPC) + { + transportClient = new CommandJsonRpcClient(); transportClient.SetEndpoint(baseUrl, appName, headers); - } else { + } + else + { throw new Exception("Invalid transport type: " + transportType); } @@ -60,81 +74,95 @@ public void SetTransport(CommandTransportType transportType) { } // - public void SetEndpoint(string baseUrl, string appName, Dictionary headers = null) { + public void SetEndpoint(string baseUrl, string appName, Dictionary headers = null) + { this.baseUrl = baseUrl; this.appName = appName; this.headers = new Dictionary(headers); - if (transportClient != null) { + if (transportClient != null) + { transportClient.SetEndpoint(this.baseUrl, this.appName, this.headers); } } // - private void SendBatch() { - mage.eventManager.emit("io.send", null); + private void SendBatch() + { + Mage.EventManager.Emit("io.send", null); - lock ((object)this) { + lock ((object)this) + { // Swap batches around locking the queue sendingBatch = currentBatch; currentBatch = new CommandBatch(nextQueryId++); // Execute pre-serialisation message hooks - if (preSerialiseHook != null) { + if (preSerialiseHook != null) + { preSerialiseHook.Invoke(sendingBatch); } // Serialise the batch - logger.debug("Serialising batch: " + sendingBatch.queryId); + Logger.Debug("Serialising batch: " + sendingBatch.QueryId); transportClient.SerialiseBatch(sendingBatch); // Execute pre-network message hooks - if (preNetworkHook != null) { + if (preNetworkHook != null) + { preNetworkHook.Invoke(sendingBatch); } // Send the batch - logger.debug("Sending batch: " + sendingBatch.queryId); + Logger.Debug("Sending batch: " + sendingBatch.QueryId); transportClient.SendBatch(sendingBatch); } } // Resend batch - public void Resend() { - mage.eventManager.emit("io.resend", null); + public void Resend() + { + Mage.EventManager.Emit("io.resend", null); - logger.debug("Re-sending batch: " + sendingBatch.queryId); + Logger.Debug("Re-sending batch: " + sendingBatch.QueryId); transportClient.SendBatch(sendingBatch); } // - private void BatchComplete() { - mage.eventManager.emit("io.response", null); + private void BatchComplete() + { + Mage.EventManager.Emit("io.response", null); - lock ((object)this) { + lock ((object)this) + { sendingBatch = null; // Check if next queued batch should be sent as well - if (currentBatch.batchItems.Count > 0) { + if (currentBatch.BatchItems.Count > 0) + { SendBatch(); } } } // - private void TransportError(string errorType, Exception error) { - logger.data(error).error("Error when sending command batch request '" + errorType + "'"); - mage.eventManager.emit("io.error." + errorType, null); + private void TransportError(string errorType, Exception error) + { + Logger.Data(error).Error("Error when sending command batch request '" + errorType + "'"); + Mage.EventManager.Emit("io.error." + errorType, null); } // Try and send a command right away if there is nothing being sent. - public void SendCommand(string commandName, JObject parameters, Action cb) { - lock ((object)this) { + public void SendCommand(string commandName, JObject parameters, Action cb) + { + lock ((object)this) + { // Add command to queue currentBatch.Queue(commandName, parameters, cb); // Check if we are busy and should only queue - if (sendingBatch != null) { + if (sendingBatch != null) + { return; } @@ -144,8 +172,10 @@ public void SendCommand(string commandName, JObject parameters, Action cb) { - lock ((object)this) { + public void PiggyBackCommand(string commandName, JObject parameters, Action cb) + { + lock ((object)this) + { currentBatch.Queue(commandName, parameters, cb); } } diff --git a/Mage/CommandCenter/TransportClient/CommandHTTPClient.cs b/Mage/CommandCenter/TransportClient/CommandHTTPClient.cs index 86ff736..b1efa7f 100644 --- a/Mage/CommandCenter/TransportClient/CommandHTTPClient.cs +++ b/Mage/CommandCenter/TransportClient/CommandHTTPClient.cs @@ -11,117 +11,141 @@ using Wizcorp.MageSDK.MageClient.Command; using Wizcorp.MageSDK.Network.Http; -namespace Wizcorp.MageSDK.Command.Client { - public class CommandHttpClientCache { - public string batchUrl; - public string postData; - public Dictionary headers; - - public CommandHttpClientCache(string batchUrl, string postData, Dictionary headers) { - this.batchUrl = batchUrl; - this.postData = postData; - this.headers = headers; +namespace Wizcorp.MageSDK.Command.Client +{ + public class CommandHttpClient : CommandTransportClient + { + private Mage Mage + { + get { return Mage.Instance; } } - } - public class CommandHTTPClient : CommandTransportClient { - private Mage mage { get { return Mage.Instance; } } - private Logger logger { get { return mage.logger("CommandHTTPClient"); } } + private Logger Logger + { + get { return Mage.Logger("CommandHttpClient"); } + } // private string endpoint; private Dictionary headers; // - public override void SetEndpoint(string baseUrl, string appName, Dictionary headers = null) { - this.endpoint = baseUrl + "/" + appName; - this.headers = new Dictionary(headers); + public override void SetEndpoint(string baseUrl, string appName, Dictionary headers = null) + { + endpoint = baseUrl + "/" + appName; + headers = new Dictionary(headers); } // - public override void SerialiseBatch(CommandBatch commandBatch) { + public override void SerialiseBatch(CommandBatch commandBatch) + { List commands = new List(); List data = new List(); // Attach batch headers to post data JArray batchHeaders = new JArray(); - for (int batchHeaderI = 0; batchHeaderI < commandBatch.batchHeaders.Count; batchHeaderI += 1) { - Dictionary batchHeader = commandBatch.batchHeaders[batchHeaderI]; + for (int batchHeaderI = 0; batchHeaderI < commandBatch.BatchHeaders.Count; batchHeaderI += 1) + { + Dictionary batchHeader = commandBatch.BatchHeaders[batchHeaderI]; batchHeaders.Add(JObject.FromObject(batchHeader)); } data.Add(batchHeaders.ToString(Newtonsoft.Json.Formatting.None)); // Attach command names to url and parameters to post data - for (int batchItemI = 0; batchItemI < commandBatch.batchItems.Count; batchItemI += 1) { - CommandBatchItem commandItem = commandBatch.batchItems[batchItemI]; - commands.Add(commandItem.commandName); - data.Add(commandItem.parameters.ToString(Newtonsoft.Json.Formatting.None)); - logger.data(commandItem.parameters).verbose("sending command: " + commandItem.commandName); + for (int batchItemI = 0; batchItemI < commandBatch.BatchItems.Count; batchItemI += 1) + { + CommandBatchItem commandItem = commandBatch.BatchItems[batchItemI]; + commands.Add(commandItem.CommandName); + data.Add(commandItem.Parameters.ToString(Newtonsoft.Json.Formatting.None)); + Logger.Data(commandItem.Parameters).Verbose("sending command: " + commandItem.CommandName); } - string batchUrl = endpoint + "/" + String.Join(",", commands.ToArray()) + "?queryId=" + commandBatch.queryId.ToString(); + string batchUrl = endpoint + "/" + String.Join(",", commands.ToArray()) + "?queryId=" + commandBatch.QueryId.ToString(); string postData = string.Join("\n", data.ToArray()); // Cached the serialisation - commandBatch.serialisedCache = (object)new CommandHttpClientCache( + commandBatch.SerialisedCache = (object)new CommandHttpClientCache( batchUrl, postData, - new Dictionary(this.headers) + (headers != null) ? new Dictionary(headers) : new Dictionary() ); } // - public override void SendBatch(CommandBatch commandBatch) { + public override void SendBatch(CommandBatch commandBatch) + { // Extract serialisation from cache - CommandHttpClientCache serialisedCache = (CommandHttpClientCache)commandBatch.serialisedCache; - string batchUrl = serialisedCache.batchUrl; - string postData = serialisedCache.postData; - Dictionary headers = serialisedCache.headers; + CommandHttpClientCache serialisedCache = (CommandHttpClientCache)commandBatch.SerialisedCache; + string batchUrl = serialisedCache.BatchUrl; + string postData = serialisedCache.PostData; + Dictionary headers = serialisedCache.Headers; // Send HTTP request - SendRequest(batchUrl, postData, headers, (JArray responseArray) => { + SendRequest(batchUrl, postData, headers, responseArray => { // Process each command response - try { - for (int batchId = 0; batchId < responseArray.Count; batchId += 1) { - JArray commandResponse = responseArray[batchId] as JArray; - CommandBatchItem commandItem = commandBatch.batchItems[batchId]; - string commandName = commandItem.commandName; - Action commandCb = commandItem.cb; + try + { + for (var batchId = 0; batchId < responseArray.Count; batchId += 1) + { + var commandResponse = responseArray[batchId] as JArray; + if (commandResponse == null) + { + throw new Exception("Response item " + batchId + " is not an Array:" + responseArray); + } + + CommandBatchItem commandItem = commandBatch.BatchItems[batchId]; + string commandName = commandItem.CommandName; + Action commandCb = commandItem.Cb; // Check if there are any events attached to this request - if (commandResponse.Count >= 3) { - logger.verbose("[" + commandName + "] processing events"); - mage.eventManager.emitEventList((JArray)commandResponse[2]); + if (commandResponse.Count >= 3) + { + Logger.Verbose("[" + commandName + "] processing events"); + Mage.EventManager.EmitEventList((JArray)commandResponse[2]); } // Check if the response was an error - if (commandResponse[0].Type != JTokenType.Null) { - logger.verbose("[" + commandName + "] server error"); + if (commandResponse[0].Type != JTokenType.Null) + { + Logger.Verbose("[" + commandName + "] server error"); commandCb(new Exception(commandResponse[0].ToString()), null); - return; + continue; } // Pull off call result object, if it doesn't exist - logger.verbose("[" + commandName + "] call response"); - commandCb(null, commandResponse[1]); + Logger.Verbose("[" + commandName + "] call response"); + + try + { + commandCb(null, commandResponse[1]); + } + catch (Exception error) + { + Logger.Data(error).Error("Error during command callback"); + } } - } catch (Exception error) { - logger.data(error).error("Error when processing command batch responses"); + } + catch (Exception error) + { + Logger.Data(error).Error("Error when processing command batch responses"); } }); } - private void SendRequest(string batchUrl, string postData, Dictionary headers, Action cb) { - HTTPRequest.Post(batchUrl, "", postData, headers, mage.cookies, (Exception requestError, string responseString) => { - logger.verbose("Recieved response: " + responseString); + private void SendRequest(string batchUrl, string postData, Dictionary headers, Action cb) + { + HttpRequest.Post(batchUrl, "", postData, headers, Mage.Cookies, (requestError, responseString) => { + Logger.Verbose("Recieved response: " + responseString); // Check if there was a transport error - if (requestError != null) { - string error = "network"; + if (requestError != null) + { + var error = "network"; // On error - var httpError = requestError as HTTPRequestException; - if (httpError != null && httpError.Status == 503) { + var httpError = requestError as HttpRequestException; + if (httpError != null && httpError.Status == 503) + { error = "maintenance"; } @@ -131,9 +155,12 @@ private void SendRequest(string batchUrl, string postData, Dictionary Headers; + + public CommandHttpClientCache(string batchUrl, string postData, Dictionary headers) + { + BatchUrl = batchUrl; + PostData = postData; + Headers = headers; + } +} diff --git a/Mage/CommandCenter/TransportClient/CommandJSONRPCClient.cs b/Mage/CommandCenter/TransportClient/CommandJSONRPCClient.cs index 727d60b..9d930ea 100644 --- a/Mage/CommandCenter/TransportClient/CommandJSONRPCClient.cs +++ b/Mage/CommandCenter/TransportClient/CommandJSONRPCClient.cs @@ -7,30 +7,42 @@ using Wizcorp.MageSDK.MageClient.Command; using Wizcorp.MageSDK.Network.JsonRpc; -namespace Wizcorp.MageSDK.Command.Client { - public class CommandJSONRPCClient : CommandTransportClient { - private Mage mage { get { return Mage.Instance; } } - private Logger logger { get { return mage.logger("CommandJSONRPCClient"); } } +namespace Wizcorp.MageSDK.Command.Client +{ + public class CommandJsonRpcClient : CommandTransportClient + { + private Mage Mage + { + get { return Mage.Instance; } + } + + private Logger Logger + { + get { return Mage.Logger("CommandJsonRpcClient"); } + } - private JSONRPC rpcClient = new JSONRPC(); + private JsonRpc rpcClient = new JsonRpc(); // - public override void SetEndpoint(string baseUrl, string appName, Dictionary headers = null) { + public override void SetEndpoint(string baseUrl, string appName, Dictionary headers = null) + { rpcClient.SetEndpoint(baseUrl + "/" + appName + "/jsonrpc", headers); } // - public override void SerialiseBatch(CommandBatch commandBatch) { - logger.verbose("THIS TRANSPORT CLIENT IS NOT IMPLEMENTED"); + public override void SerialiseBatch(CommandBatch commandBatch) + { + Logger.Verbose("THIS TRANSPORT CLIENT IS NOT IMPLEMENTED"); throw new Exception("THIS TRANSPORT CLIENT IS NOT IMPLEMENTED"); } // - public override void SendBatch(CommandBatch commandBatch) { + public override void SendBatch(CommandBatch commandBatch) + { // NOTE: This transport client cannot be implemented yet as JSON RPC support is // terminally broken in MAGE (does not support queryId and response caching). // Until this is fixed, this transport client cannot be used or completed. - logger.verbose("THIS TRANSPORT CLIENT IS NOT IMPLEMENTED"); + Logger.Verbose("THIS TRANSPORT CLIENT IS NOT IMPLEMENTED"); throw new Exception("THIS TRANSPORT CLIENT IS NOT IMPLEMENTED"); /* diff --git a/Mage/CommandCenter/TransportClient/CommandTransportClient.cs b/Mage/CommandCenter/TransportClient/CommandTransportClient.cs index 8363c1e..913ff5d 100644 --- a/Mage/CommandCenter/TransportClient/CommandTransportClient.cs +++ b/Mage/CommandCenter/TransportClient/CommandTransportClient.cs @@ -3,13 +3,10 @@ using Wizcorp.MageSDK.MageClient.Command; -namespace Wizcorp.MageSDK.CommandCenter.Client { - public enum CommandTransportType { - HTTP, - JSONRPC - } - - public abstract class CommandTransportClient { +namespace Wizcorp.MageSDK.CommandCenter.Client +{ + public abstract class CommandTransportClient + { public Action OnSendComplete; public Action OnTransportError; diff --git a/Mage/CommandCenter/TransportClient/CommandTransportType.cs b/Mage/CommandCenter/TransportClient/CommandTransportType.cs new file mode 100644 index 0000000..27b26ba --- /dev/null +++ b/Mage/CommandCenter/TransportClient/CommandTransportType.cs @@ -0,0 +1,8 @@ +namespace Wizcorp.MageSDK.Command.Client +{ + public enum CommandTransportType + { + HTTP, + JSONRPC + } +} \ No newline at end of file diff --git a/Mage/EventManager.cs b/Mage/EventManager.cs index 6c200e0..d747bc2 100644 --- a/Mage/EventManager.cs +++ b/Mage/EventManager.cs @@ -3,13 +3,25 @@ using Wizcorp.MageSDK.Event; using Wizcorp.MageSDK.Log; -namespace Wizcorp.MageSDK.MageClient { - public class EventManager : EventEmitter { - private Mage mage { get { return Mage.Instance; } } - private Logger logger { get { return mage.logger("eventManager"); } } +namespace Wizcorp.MageSDK.MageClient +{ + public class EventManager : EventEmitter + { + private Mage Mage + { + get { return Mage.Instance; } + } + + private Logger Logger + { + get { return Mage.Logger("EventManager"); } + } + - public void emitEventList(JArray events) { - foreach (JToken responseEvent in events) { + public void EmitEventList(JArray events) + { + foreach (JToken responseEvent in events) + { string eventTag = null; JToken eventData = null; @@ -17,24 +29,27 @@ public void emitEventList(JArray events) { JArray eventItem = JArray.Parse(responseEvent.ToString()); // Check that event name is present - if (eventItem.Count >= 1) { + if (eventItem.Count >= 1) + { eventTag = eventItem[0].ToString(); } // Check if any event data is present - if (eventItem.Count == 2) { + if (eventItem.Count == 2) + { eventData = eventItem[1]; } // Check if there were any errors, log and skip them - if (eventTag == null || eventItem.Count > 2) { - logger.data(eventItem).error("Invalid event format:"); + if (eventTag == null || eventItem.Count > 2) + { + Logger.Data(eventItem).Error("Invalid event format:"); continue; } // Emit the event - logger.debug("Emitting '" + eventTag + "'"); - mage.eventManager.emit(eventTag, eventData); + Logger.Debug("Emitting '" + eventTag + "'"); + Mage.EventManager.Emit(eventTag, eventData); } } } diff --git a/Mage/Logger/LogEntry.cs b/Mage/Logger/LogEntry.cs index 234b3fe..19fe347 100644 --- a/Mage/Logger/LogEntry.cs +++ b/Mage/Logger/LogEntry.cs @@ -1,77 +1,90 @@ -namespace Wizcorp.MageSDK.Log { - public class LogEntry { +namespace Wizcorp.MageSDK.Log +{ + public class LogEntry + { // - public string channel; - public string context; - public object data; - public string message; + public string Channel; + public string Context; + public object Data; + public string Message; - public LogEntry(string context, object data = null) { - this.context = context; - this.data = data; + public LogEntry(string context, object data = null) + { + Context = context; + Data = data; } // - private void emitLog() { - Logger.logEmitter.emit("log", this); - Logger.logEmitter.emit("log:" + this.channel, this); + private void EmitLog() + { + Logger.LogEmitter.Emit("log", this); + Logger.LogEmitter.Emit("log:" + Channel, this); } // - public void verbose(string message) { - this.channel = "verbose"; - this.message = message; - emitLog(); + public void Verbose(string message) + { + Channel = "verbose"; + Message = message; + EmitLog(); } - public void debug(string message) { - this.channel = "debug"; - this.message = message; - emitLog(); + public void Debug(string message) + { + Channel = "debug"; + Message = message; + EmitLog(); } - public void info(string message) { - this.channel = "info"; - this.message = message; - emitLog(); + public void Info(string message) + { + Channel = "info"; + Message = message; + EmitLog(); } - public void notice(string message) { - this.channel = "notice"; - this.message = message; - emitLog(); + public void Notice(string message) + { + Channel = "notice"; + Message = message; + EmitLog(); } - public void warning(string message) { - this.channel = "warning"; - this.message = message; - emitLog(); + public void Warning(string message) + { + Channel = "warning"; + Message = message; + EmitLog(); } - public void error(string message) { - this.channel = "error"; - this.message = message; - emitLog(); + public void Error(string message) + { + Channel = "error"; + Message = message; + EmitLog(); } - public void critical(string message) { - this.channel = "critical"; - this.message = message; - emitLog(); + public void Critical(string message) + { + Channel = "critical"; + Message = message; + EmitLog(); } - public void alert(string message) { - this.channel = "alert"; - this.message = message; - emitLog(); + public void Alert(string message) + { + Channel = "alert"; + Message = message; + EmitLog(); } - public void emergency(string message) { - this.channel = "emergency"; - this.message = message; - emitLog(); + public void Emergency(string message) + { + Channel = "emergency"; + Message = message; + EmitLog(); } } } diff --git a/Mage/Logger/Logger.cs b/Mage/Logger/Logger.cs index 760b30c..011c276 100644 --- a/Mage/Logger/Logger.cs +++ b/Mage/Logger/Logger.cs @@ -4,39 +4,47 @@ using Wizcorp.MageSDK.Event; using Wizcorp.MageSDK.Log.Writers; -namespace Wizcorp.MageSDK.Log { - public class Logger { +namespace Wizcorp.MageSDK.Log +{ + public class Logger + { // - public static EventEmitter logEmitter = new EventEmitter(); + public static EventEmitter LogEmitter = new EventEmitter(); // - public static Dictionary logWriters; - public static void SetConfig(Dictionary> config) { + public static Dictionary LogWriters; + public static void SetConfig(Dictionary> config) + { // Destroy existing log writers - if (logWriters != null) { - foreach (var writer in logWriters.Values) { + if (LogWriters != null) + { + foreach (LogWriter writer in LogWriters.Values) + { writer.Dispose(); } - logWriters = null; + LogWriters = null; } // Make sure we have configured something - if (config == null) { + if (config == null) + { return; } // Create each writer with log levels - logWriters = new Dictionary(); - foreach (var property in config) { + LogWriters = new Dictionary(); + foreach (KeyValuePair> property in config) + { string writer = property.Key; List writerConfig = property.Value; - switch (writer) { + switch (writer) + { case "console": - logWriters.Add(writer, new ConsoleWriter(writerConfig) as LogWriter); + LogWriters.Add(writer, new ConsoleWriter(writerConfig)); break; case "server": - logWriters.Add(writer, new ServerWriter(writerConfig) as LogWriter); + LogWriters.Add(writer, new ServerWriter(writerConfig)); break; default: throw new Exception("Unknown Log Writer: " + writer); @@ -46,54 +54,65 @@ public static void SetConfig(Dictionary> config) { // - private string _context; + private string context; - public Logger(string context) { - _context = context; + public Logger(string context) + { + this.context = context; } // - public LogEntry data(object data) { - return new LogEntry(_context, data); + public LogEntry Data(object data) + { + return new LogEntry(context, data); } // - public void verbose(string message) { - (new LogEntry(_context)).verbose(message); + public void Verbose(string message) + { + (new LogEntry(context)).Verbose(message); } - public void debug(string message) { - (new LogEntry(_context)).debug(message); + public void Debug(string message) + { + (new LogEntry(context)).Debug(message); } - public void info(string message) { - (new LogEntry(_context)).info(message); + public void Info(string message) + { + (new LogEntry(context)).Info(message); } - public void notice(string message) { - (new LogEntry(_context)).notice(message); + public void Notice(string message) + { + (new LogEntry(context)).Notice(message); } - public void warning(string message) { - (new LogEntry(_context)).warning(message); + public void Warning(string message) + { + (new LogEntry(context)).Warning(message); } - public void error(string message) { - (new LogEntry(_context)).error(message); + public void Error(string message) + { + (new LogEntry(context)).Error(message); } - public void critical(string message) { - (new LogEntry(_context)).critical(message); + public void Critical(string message) + { + (new LogEntry(context)).Critical(message); } - public void alert(string message) { - (new LogEntry(_context)).alert(message); + public void Alert(string message) + { + (new LogEntry(context)).Alert(message); } - public void emergency(string message) { - (new LogEntry(_context)).emergency(message); + public void Emergency(string message) + { + (new LogEntry(context)).Emergency(message); } } } diff --git a/Mage/Logger/Writers/ConsoleWriter.cs b/Mage/Logger/Writers/ConsoleWriter.cs index be96b84..4232d4f 100644 --- a/Mage/Logger/Writers/ConsoleWriter.cs +++ b/Mage/Logger/Writers/ConsoleWriter.cs @@ -1,157 +1,206 @@ using System; using System.Collections.Generic; -namespace Wizcorp.MageSDK.Log.Writers { - public class ConsoleWriter : LogWriter { +namespace Wizcorp.MageSDK.Log.Writers +{ + public class ConsoleWriter : LogWriter + { private List config; - public ConsoleWriter(List logLevels) { + public ConsoleWriter(List logLevels) + { config = logLevels; - if (config.Contains("verbose")) { - Logger.logEmitter.on("log:verbose", Verbose); + if (config.Contains("verbose")) + { + Logger.LogEmitter.On("log:verbose", Verbose); } - if (config.Contains("debug")) { - Logger.logEmitter.on("log:debug", Debug); + if (config.Contains("debug")) + { + Logger.LogEmitter.On("log:debug", Debug); } - if (config.Contains("info")) { - Logger.logEmitter.on("log:info", Info); + if (config.Contains("info")) + { + Logger.LogEmitter.On("log:info", Info); } - if (config.Contains("notice")) { - Logger.logEmitter.on("log:notice", Notice); + if (config.Contains("notice")) + { + Logger.LogEmitter.On("log:notice", Notice); } - if (config.Contains("warning")) { - Logger.logEmitter.on("log:warning", Warning); + if (config.Contains("warning")) + { + Logger.LogEmitter.On("log:warning", Warning); } - if (config.Contains("error")) { - Logger.logEmitter.on("log:error", Error); + if (config.Contains("error")) + { + Logger.LogEmitter.On("log:error", Error); } - if (config.Contains("critical")) { - Logger.logEmitter.on("log:critical", Critical); + if (config.Contains("critical")) + { + Logger.LogEmitter.On("log:critical", Critical); } - if (config.Contains("alert")) { - Logger.logEmitter.on("log:alert", Alert); + if (config.Contains("alert")) + { + Logger.LogEmitter.On("log:alert", Alert); } - if (config.Contains("emergency")) { - Logger.logEmitter.on("log:emergency", Emergency); + if (config.Contains("emergency")) + { + Logger.LogEmitter.On("log:emergency", Emergency); } } - public override void Dispose() { - if (config.Contains("verbose")) { - Logger.logEmitter.off("log:verbose", Verbose); + public override void Dispose() + { + if (config.Contains("verbose")) + { + Logger.LogEmitter.Off("log:verbose", Verbose); } - if (config.Contains("debug")) { - Logger.logEmitter.off("log:debug", Debug); + if (config.Contains("debug")) + { + Logger.LogEmitter.Off("log:debug", Debug); } - if (config.Contains("info")) { - Logger.logEmitter.off("log:info", Info); + if (config.Contains("info")) + { + Logger.LogEmitter.Off("log:info", Info); } - if (config.Contains("notice")) { - Logger.logEmitter.off("log:notice", Notice); + if (config.Contains("notice")) + { + Logger.LogEmitter.Off("log:notice", Notice); } - if (config.Contains("warning")) { - Logger.logEmitter.off("log:warning", Warning); + if (config.Contains("warning")) + { + Logger.LogEmitter.Off("log:warning", Warning); } - if (config.Contains("error")) { - Logger.logEmitter.off("log:error", Error); + if (config.Contains("error")) + { + Logger.LogEmitter.Off("log:error", Error); } - if (config.Contains("critical")) { - Logger.logEmitter.off("log:critical", Critical); + if (config.Contains("critical")) + { + Logger.LogEmitter.Off("log:critical", Critical); } - if (config.Contains("alert")) { - Logger.logEmitter.off("log:alert", Alert); + if (config.Contains("alert")) + { + Logger.LogEmitter.Off("log:alert", Alert); } - if (config.Contains("emergency")) { - Logger.logEmitter.off("log:emergency", Emergency); + if (config.Contains("emergency")) + { + Logger.LogEmitter.Off("log:emergency", Emergency); } } - private string makeLogString(string channel, string context, string message) { + private string makeLogString(string channel, string context, string message) + { return String.Format("[{0}] [{1}] {2}", channel, context, message); } - private void Verbose(object sender, LogEntry logEntry) { - UnityEngine.Debug.Log(makeLogString("verbose", logEntry.context, logEntry.message)); - if (logEntry.data != null) { - UnityEngine.Debug.Log(logEntry.data); + private object makeDataString(object logData) + { + // Check if data is an excetion with a stack trace + var exception = logData as Exception; + if (exception != null && exception.StackTrace != null) + { + return exception + ":\n" + exception.StackTrace; + } + + // Otherwise log data as is using its toString function + return logData; + } + + private void Verbose(object sender, LogEntry logEntry) + { + UnityEngine.Debug.Log(makeLogString("verbose", logEntry.Context, logEntry.Message)); + if (logEntry.Data != null) + { + UnityEngine.Debug.Log(makeDataString(logEntry.Data)); } } - private void Debug(object sender, LogEntry logEntry) { - UnityEngine.Debug.Log(makeLogString("debug", logEntry.context, logEntry.message)); - if (logEntry.data != null) { - UnityEngine.Debug.Log(logEntry.data); + private void Debug(object sender, LogEntry logEntry) + { + UnityEngine.Debug.Log(makeLogString("debug", logEntry.Context, logEntry.Message)); + if (logEntry.Data != null) + { + UnityEngine.Debug.Log(makeDataString(logEntry.Data)); } } - private void Info(object sender, LogEntry logEntry) { - UnityEngine.Debug.Log(makeLogString("info", logEntry.context, logEntry.message)); - if (logEntry.data != null) { - UnityEngine.Debug.Log(logEntry.data); + private void Info(object sender, LogEntry logEntry) + { + UnityEngine.Debug.Log(makeLogString("info", logEntry.Context, logEntry.Message)); + if (logEntry.Data != null) + { + UnityEngine.Debug.Log(makeDataString(logEntry.Data)); } } - private void Notice(object sender, LogEntry logEntry) { - UnityEngine.Debug.Log(makeLogString("notice", logEntry.context, logEntry.message)); - if (logEntry.data != null) { - UnityEngine.Debug.Log(logEntry.data); + private void Notice(object sender, LogEntry logEntry) + { + UnityEngine.Debug.Log(makeLogString("notice", logEntry.Context, logEntry.Message)); + if (logEntry.Data != null) + { + UnityEngine.Debug.Log(makeDataString(logEntry.Data)); } } - private void Warning(object sender, LogEntry logEntry) { - UnityEngine.Debug.LogWarning(makeLogString("warning", logEntry.context, logEntry.message)); - if (logEntry.data != null) { - UnityEngine.Debug.LogWarning(logEntry.data); + private void Warning(object sender, LogEntry logEntry) + { + UnityEngine.Debug.LogWarning(makeLogString("warning", logEntry.Context, logEntry.Message)); + if (logEntry.Data != null) + { + UnityEngine.Debug.LogWarning(makeDataString(logEntry.Data)); } } - private void Error(object sender, LogEntry logEntry) { - UnityEngine.Debug.LogError(makeLogString("error", logEntry.context, logEntry.message)); - if (logEntry.data != null) { - UnityEngine.Debug.LogError(logEntry.data); + private void Error(object sender, LogEntry logEntry) + { + UnityEngine.Debug.LogError(makeLogString("error", logEntry.Context, logEntry.Message)); + if (logEntry.Data != null) + { + UnityEngine.Debug.LogError(makeDataString(logEntry.Data)); } } - private void Critical(object sender, LogEntry logEntry) { - UnityEngine.Debug.LogError(makeLogString("critical", logEntry.context, logEntry.message)); - if (logEntry.data != null) { - if (logEntry.data is Exception && (logEntry.data as Exception).StackTrace != null) { - Exception excpt = logEntry.data as Exception; - UnityEngine.Debug.LogError(excpt.ToString() + ":\n" + excpt.StackTrace.ToString()); - } else { - UnityEngine.Debug.LogError(logEntry.data); - } + private void Critical(object sender, LogEntry logEntry) + { + UnityEngine.Debug.LogError(makeLogString("critical", logEntry.Context, logEntry.Message)); + if (logEntry.Data != null) + { + UnityEngine.Debug.LogError(makeDataString(logEntry.Data)); } } - private void Alert(object sender, LogEntry logEntry) { - UnityEngine.Debug.LogError(makeLogString("alert", logEntry.context, logEntry.message)); - if (logEntry.data != null) { - UnityEngine.Debug.LogError(logEntry.data); + private void Alert(object sender, LogEntry logEntry) + { + UnityEngine.Debug.LogError(makeLogString("alert", logEntry.Context, logEntry.Message)); + if (logEntry.Data != null) + { + UnityEngine.Debug.LogError(makeDataString(logEntry.Data)); } } - private void Emergency(object sender, LogEntry logEntry) { - UnityEngine.Debug.LogError(makeLogString("emergency", logEntry.context, logEntry.message)); - if (logEntry.data != null) { - UnityEngine.Debug.LogError(logEntry.data); + private void Emergency(object sender, LogEntry logEntry) + { + UnityEngine.Debug.LogError(makeLogString("emergency", logEntry.Context, logEntry.Message)); + if (logEntry.Data != null) + { + UnityEngine.Debug.LogError(makeDataString(logEntry.Data)); } } } diff --git a/Mage/Logger/Writers/LogWriter.cs b/Mage/Logger/Writers/LogWriter.cs index 42f3f17..e7b7d15 100644 --- a/Mage/Logger/Writers/LogWriter.cs +++ b/Mage/Logger/Writers/LogWriter.cs @@ -1,5 +1,7 @@ -namespace Wizcorp.MageSDK.Log.Writers { - public abstract class LogWriter { +namespace Wizcorp.MageSDK.Log.Writers +{ + public abstract class LogWriter + { public abstract void Dispose(); } } diff --git a/Mage/Logger/Writers/ServerWriter.cs b/Mage/Logger/Writers/ServerWriter.cs index 7c7676f..6d0e41f 100644 --- a/Mage/Logger/Writers/ServerWriter.cs +++ b/Mage/Logger/Writers/ServerWriter.cs @@ -1,45 +1,51 @@ -using System; using System.Collections.Generic; using Newtonsoft.Json.Linq; using Wizcorp.MageSDK.MageClient; -namespace Wizcorp.MageSDK.Log.Writers { - public class ServerWriter : LogWriter { - protected Mage mage { get { return Mage.Instance; } } +namespace Wizcorp.MageSDK.Log.Writers +{ + public class ServerWriter : LogWriter + { + protected Mage Mage { get { return Mage.Instance; } } private List config; - public ServerWriter(List logLevels) { + public ServerWriter(List logLevels) + { config = logLevels; - Logger.logEmitter.on("log", HandleLog); + Logger.LogEmitter.On("log", HandleLog); } - public override void Dispose() { - Logger.logEmitter.off("log", HandleLog); + public override void Dispose() + { + Logger.LogEmitter.Off("log", HandleLog); } - private void HandleLog(object sender, LogEntry logEntry) { - if (config == null || !config.Contains(logEntry.channel)) { + private void HandleLog(object sender, LogEntry logEntry) + { + if (config == null || !config.Contains(logEntry.Channel)) + { return; } - string contextMessage = "[" + logEntry.context + "] " + logEntry.message; + string contextMessage = "[" + logEntry.Context + "] " + logEntry.Message; JObject dataObject = null; - if (logEntry.data != null) { - dataObject = JObject.FromObject(logEntry.data); + if (logEntry.Data != null) + { + dataObject = JObject.FromObject(logEntry.Data); } JObject arguments = new JObject(); - arguments.Add("channel", new JValue(logEntry.channel)); + arguments.Add("channel", new JValue(logEntry.Channel)); arguments.Add("message", new JValue(contextMessage)); arguments.Add("data", dataObject); - mage.commandCenter.SendCommand("logger.sendReport", arguments, (Exception error, JToken result) => { + Mage.CommandCenter.SendCommand("logger.sendReport", arguments, (error, result) => { // if (error) // We honestly can't do anything about this.... }); diff --git a/Mage/Mage.cs b/Mage/Mage.cs index 07ff64c..a5cbd03 100644 --- a/Mage/Mage.cs +++ b/Mage/Mage.cs @@ -7,44 +7,44 @@ using Wizcorp.MageSDK.Log; using Wizcorp.MageSDK.MageClient.Message; using Wizcorp.MageSDK.Network.Http; +using Wizcorp.MageSDK.Unity; using Wizcorp.MageSDK.Utils; -namespace Wizcorp.MageSDK.MageClient { - public class MageSetupStatus { - public bool done = false; - public Exception error = null; - } - - - public class Mage : Singleton { +namespace Wizcorp.MageSDK.MageClient +{ + public class Mage : Singleton + { // - public EventManager eventManager; - public Session session; - public Command.CommandCenter commandCenter; - public MessageStream messageStream; - public Archivist archivist; + public EventManager EventManager; + public Session Session; + public Command.CommandCenter CommandCenter; + public MessageStream MessageStream; + public Archivist Archivist; - private Logger _logger; + private Logger logger; // - string baseUrl; - string appName; - Dictionary headers; - public CookieContainer cookies; + private string baseUrl; + private string appName; + private Dictionary headers; + public CookieContainer Cookies; // - private Dictionary _loggers = new Dictionary(); - public Logger logger(string context = null) { - if (string.IsNullOrEmpty(context)) { + private Dictionary loggers = new Dictionary(); + public Logger Logger(string context = null) + { + if (string.IsNullOrEmpty(context)) + { context = "Default"; } - if (_loggers.ContainsKey(context)) { - return _loggers[context]; + if (loggers.ContainsKey(context)) + { + return loggers[context]; } - Logger newLogger = new Logger(context); - _loggers.Add(context, new Logger(context)); + var newLogger = new Logger(context); + loggers.Add(context, newLogger); return newLogger; } @@ -52,166 +52,187 @@ public Logger logger(string context = null) { // Avoid putting setup logic in the contstuctor. Only things that can be // carried between game sessions should go here. Otherwise we need to be // able to re-initialize them inside the setup function. - public Mage() { + public Mage() + { // Setup log writters - _logger = logger("mage"); + logger = Logger("mage"); // TODO: properly check the damn certificate, for now ignore invalid ones (fix issue on Android/iOS) ServicePointManager.ServerCertificateValidationCallback += (o, cert, chain, errors) => true; } // - public void setEndpoints(string baseUrl, string appName, Dictionary headers = null) { + public void SetEndpoints(string baseUrl, string appName, Dictionary headers = null) + { this.baseUrl = baseUrl; this.appName = appName; this.headers = new Dictionary(headers); - if (commandCenter != null) { - commandCenter.SetEndpoint(baseUrl, appName, this.headers); + if (CommandCenter != null) + { + CommandCenter.SetEndpoint(baseUrl, appName, this.headers); } - if (messageStream != null) { - messageStream.SetEndpoint(baseUrl, this.headers); + if (MessageStream != null) + { + MessageStream.SetEndpoint(baseUrl, this.headers); } } // - public void Setup(Action cb) { + public void Setup(Action cb) + { // Cleanup any existing internal modules - if (messageStream != null) { - messageStream.Dispose(); + if (MessageStream != null) + { + MessageStream.Dispose(); } // Instantiate Singletons UnityApplicationState.Instantiate(); - HTTPRequestManager.Instantiate(); + HttpRequestManager.Instantiate(); // Create a shared cookie container - cookies = new CookieContainer(); + Cookies = new CookieContainer(); // Initialize mage internal modules - eventManager = new EventManager(); - commandCenter = new CommandCenter(); - messageStream = new MessageStream(); + EventManager = new EventManager(); + CommandCenter = new Command.CommandCenter(); + MessageStream = new MessageStream(); - session = new Session(); - archivist = new Archivist(); + Session = new Session(); + Archivist = new Archivist(); // Set endpoints - commandCenter.SetEndpoint(baseUrl, appName, headers); - messageStream.SetEndpoint(baseUrl, headers); + CommandCenter.SetEndpoint(baseUrl, appName, headers); + MessageStream.SetEndpoint(baseUrl, headers); cb(null); } // - public void SetupModules(List moduleNames, Action cb) { + public void SetupModules(List moduleNames, Action cb) + { // Setup application modules - _logger.info("Setting up modules"); - Async.each(moduleNames, (string moduleName, Action callback) => { - _logger.info("Setting up module: " + moduleName); - - // Use reflection to find module by name - Assembly assembly = Assembly.GetExecutingAssembly(); - Type[] assemblyTypes = assembly.GetTypes(); - foreach (Type t in assemblyTypes) { - if (moduleName == t.Name) { - BindingFlags staticProperty = BindingFlags.Static | BindingFlags.GetProperty; - BindingFlags publicMethod = BindingFlags.Public | BindingFlags.InvokeMethod; - - // Grab module instance from singleton base - var singletonType = typeof(Singleton<>).MakeGenericType(t); - Object instance = singletonType.InvokeMember("Instance", staticProperty, null, null, null); - - // Setup module - var moduleType = typeof(Module<>).MakeGenericType(t); - Async.series(new List>>() { - (Action callbackInner) => { - // Setup module user commands - object[] arguments = new object[]{callbackInner}; - moduleType.InvokeMember("setupUsercommands", publicMethod, null, instance, arguments); - }, - (Action callbackInner) => { - // Setup module static data - object[] arguments = new object[]{callbackInner}; - moduleType.InvokeMember("setupStaticData", publicMethod, null, instance, arguments); - } - }, (Exception error) => { - if (error != null) { - callback(error); - return; - } + logger.Info("Setting up modules"); + Async.Each( + moduleNames, + (moduleName, callback) => { + logger.Info("Setting up module: " + moduleName); + + // Use reflection to find module by name + Assembly assembly = Assembly.GetExecutingAssembly(); + Type[] assemblyTypes = assembly.GetTypes(); + foreach (Type t in assemblyTypes) + { + if (moduleName == t.Name) + { + BindingFlags staticProperty = BindingFlags.Static | BindingFlags.GetProperty; + BindingFlags publicMethod = BindingFlags.Public | BindingFlags.InvokeMethod; + + // Grab module instance from singleton base + var singletonType = typeof(Singleton<>).MakeGenericType(t); + Object instance = singletonType.InvokeMember("Instance", staticProperty, null, null, null); + + // Setup module + Type moduleType = typeof(Module<>).MakeGenericType(t); + Type t1 = t; + Async.Series( + new List>>() { + // Setup module user commands + callbackInner => { + moduleType.InvokeMember("SetupUsercommands", publicMethod, null, instance, new object[] { callbackInner }); + }, + // Setup module static data + callbackInner => { + moduleType.InvokeMember("SetupStaticData", publicMethod, null, instance, new object[] { callbackInner }); + } + }, + error => { + if (error != null) + { + callback(error); + return; + } + + // Check if the module has a setup method + if (t1.GetMethod("Setup") == null) + { + Logger(moduleName).Info("No setup function"); + callback(null); + return; + } + + // Invoke the setup method on the module + Logger(moduleName).Info("Executing setup function"); + t1.InvokeMember("Setup", publicMethod, null, instance, new object[] { callback }); + } + ); - // Check if the module has a setup method - if (t.GetMethod("Setup") == null) { - logger(moduleName).info("No setup function"); - callback(null); return; } + } - // Invoke the setup method on the module - logger(moduleName).info("Executing setup function"); - object[] arguments = new object[] { callback }; - t.InvokeMember("Setup", publicMethod, null, instance, arguments); - }); - + // If nothing found throw an error + callback(new Exception("Can't find module " + moduleName)); + }, + error => { + if (error != null) + { + logger.Data(error).Error("Setup failed!"); + cb(error); return; } - } - // If nothing found throw an error - callback(new Exception("Can't find module " + moduleName)); - }, (Exception error) => { - if (error != null) { - _logger.data(error).error("Setup failed!"); - cb(error); - return; + logger.Info("Setup complete"); + cb(null); } - - _logger.info("Setup complete"); - cb(null); - }); + ); } // - public IEnumerator SetupTask(Action cb) { + public IEnumerator SetupTask(Action cb) + { // Execute async setup function - MageSetupStatus setupStatus = new MageSetupStatus(); - Setup((Exception error) => { - setupStatus.error = error; - setupStatus.done = true; + var setupStatus = new MageSetupStatus(); + Setup(error => { + setupStatus.Error = error; + setupStatus.Done = true; }); // Wait for setup to return - while (!setupStatus.done) { + while (!setupStatus.Done) + { yield return null; } // Call callback with error if there is one - cb(setupStatus.error); + cb(setupStatus.Error); } // - public IEnumerator SetupModulesTask(List moduleNames, Action cb) { + public IEnumerator SetupModulesTask(List moduleNames, Action cb) + { // Execute async setup function - MageSetupStatus setupStatus = new MageSetupStatus(); - SetupModules(moduleNames, (Exception error) => { - setupStatus.error = error; - setupStatus.done = true; + var setupStatus = new MageSetupStatus(); + SetupModules(moduleNames, error => { + setupStatus.Error = error; + setupStatus.Done = true; }); // Wait for setup to return - while (!setupStatus.done) { + while (!setupStatus.Done) + { yield return null; } // Call callback with error if there is one - cb(setupStatus.error); + cb(setupStatus.Error); } } } diff --git a/Mage/MageSetupStatus.cs b/Mage/MageSetupStatus.cs new file mode 100644 index 0000000..68f821d --- /dev/null +++ b/Mage/MageSetupStatus.cs @@ -0,0 +1,10 @@ +using System; + +namespace Wizcorp.MageSDK.MageClient +{ + public class MageSetupStatus + { + public bool Done = false; + public Exception Error = null; + } +} diff --git a/Mage/MessageStream/MessageStream.cs b/Mage/MessageStream/MessageStream.cs index 0a67a91..3e77caf 100644 --- a/Mage/MessageStream/MessageStream.cs +++ b/Mage/MessageStream/MessageStream.cs @@ -7,18 +7,25 @@ using Wizcorp.MageSDK.Log; using Wizcorp.MageSDK.MageClient.Message.Client; -#if UNITY_EDITOR -using Wizcorp.MageSDK.Editor; -#endif +using Wizcorp.MageSDK.Unity; + +namespace Wizcorp.MageSDK.MageClient.Message +{ + public class MessageStream + { + private static Mage Mage + { + get { return Mage.Instance; } + } -namespace Wizcorp.MageSDK.MageClient.Message { - public class MessageStream { - private Mage mage { get { return Mage.Instance; } } - private Logger logger { get { return mage.logger("messagestream"); } } + private static Logger Logger + { + get { return Mage.Logger("MessageStream"); } + } // Endpoint and credentials private string endpoint; - Dictionary headers; + private Dictionary headers; private string sessionKey; // Current transport client @@ -32,194 +39,222 @@ public class MessageStream { // - private void initializeMessageList() { + private void InitializeMessageList() + { currentMessageId = -1; largestMessageId = -1; messageQueue = new Dictionary(); confirmIds = new List(); - logger.debug("Initialized message queue"); + Logger.Debug("Initialized message queue"); } // Constructor - public MessageStream(TransportType transport = TransportType.LONGPOLLING) { + public MessageStream(TransportType transport = TransportType.LONGPOLLING) + { // - initializeMessageList(); + InitializeMessageList(); // Start transport client when session is acquired - mage.eventManager.on("session.set", (object sender, JToken session) => { + Mage.EventManager.On("session.set", (sender, session) => { sessionKey = UnityEngine.WWW.EscapeURL(session["key"].ToString()); - transportClient.start(); + transportClient.Start(); }); // Stop the message client when session is lost - mage.eventManager.on("session.unset", (object sender, JToken reason) => { - transportClient.stop(); - initializeMessageList(); + Mage.EventManager.On("session.unset", (sender, reason) => { + transportClient.Stop(); + InitializeMessageList(); sessionKey = null; }); // Also stop the message client when the application is stopped -#if UNITY_EDITOR - UnityEditorPlayMode.onEditorModeChanged += (EditorPlayModeState newState) => { - if (newState == EditorPlayModeState.Stopped) { - transportClient.stop(); - initializeMessageList(); + #if UNITY_EDITOR + UnityEditorPlayMode.OnEditorModeChanged += newState => { + if (newState == EditorPlayModeState.Stopped) + { + transportClient.Stop(); + InitializeMessageList(); sessionKey = null; } - if (newState == EditorPlayModeState.Paused && transportClient.running) { - transportClient.stop(); + if (newState == EditorPlayModeState.Paused && transportClient.running) + { + transportClient.Stop(); } - if (newState == EditorPlayModeState.Playing && !transportClient.running && sessionKey != null) { - transportClient.start(); + if (newState == EditorPlayModeState.Playing && !transportClient.running && sessionKey != null) + { + transportClient.Start(); } }; -#endif - UnityApplicationState.Instance.onAppStateChanged += (bool pauseStatus) => { - if (pauseStatus && transportClient.running) { - transportClient.stop(); + #endif + + UnityApplicationState.Instance.OnAppStateChanged += pauseStatus => { + if (pauseStatus && transportClient.running) + { + transportClient.Stop(); } - if (!pauseStatus && !transportClient.running && sessionKey != null) { - transportClient.start(); + if (!pauseStatus && !transportClient.running && sessionKey != null) + { + transportClient.Start(); } }; // Set the selected transport client (or the default) - this.SetTransport(transport); + SetTransport(transport); } // - public void Dispose() { + public void Dispose() + { // Stop the transport client if it exists - if (transportClient != null) { - transportClient.stop(); + if (transportClient != null) + { + transportClient.Stop(); } - initializeMessageList(); + InitializeMessageList(); sessionKey = null; } // Updates URI and credentials - public void SetEndpoint(string baseURL, Dictionary headers = null) { + public void SetEndpoint(string baseURL, Dictionary headers = null) + { this.endpoint = baseURL + "/msgstream"; this.headers = headers; } // Sets up given transport client type - public void SetTransport(TransportType transport) { + public void SetTransport(TransportType transport) + { // Stop existing transport client if any, when nulled out it will be collected // by garbage collecter after existing connections have been terminated. - if (transportClient != null) { - transportClient.stop(); + if (transportClient != null) + { + transportClient.Stop(); transportClient = null; } // Create new transport client instance - if (transport == TransportType.SHORTPOLLING) { - Func getShortPollingEndpoint = () => { - return getHttpPollingEndpoint("shortpolling"); - }; - - transportClient = new ShortPolling(getShortPollingEndpoint, getHttpHeaders, processMessagesString, 5000) as TransportClient; - } else if (transport == TransportType.LONGPOLLING) { - Func getLongPollingEndpoint = () => { - return getHttpPollingEndpoint("longpolling"); - }; - - transportClient = new LongPolling(getLongPollingEndpoint, getHttpHeaders, processMessagesString) as TransportClient; - } else { - throw new Exception("Invalid transport type: " + transport); + switch (transport) + { + case TransportType.SHORTPOLLING: + Func getShortPollingEndpoint = () => { return GetHttpPollingEndpoint("shortpolling"); }; + transportClient = new ShortPolling(getShortPollingEndpoint, GetHttpHeaders, ProcessMessagesString); + break; + case TransportType.LONGPOLLING: + Func getLongPollingEndpoint = () => { return GetHttpPollingEndpoint("longpolling"); }; + transportClient = new LongPolling(getLongPollingEndpoint, GetHttpHeaders, ProcessMessagesString); + break; + default: + throw new Exception("Invalid transport type: " + transport); } } // Returns the endpoint URL for polling transport clients i.e. longpolling and shortpolling - private string getHttpPollingEndpoint(string transport) { - string endpoint = this.endpoint + "?transport=" + transport + "&sessionKey=" + sessionKey; - if (confirmIds.Count > 0) { - endpoint += "&confirmIds=" + string.Join(",", confirmIds.ToArray()); + private string GetHttpPollingEndpoint(string transport) + { + string url = endpoint + "?transport=" + transport + "&sessionKey=" + sessionKey; + if (confirmIds.Count > 0) + { + url += "&confirmIds=" + string.Join(",", confirmIds.ToArray()); confirmIds.Clear(); } - return endpoint; + return url; } // Returns the required HTTP headers - private Dictionary getHttpHeaders() { + private Dictionary GetHttpHeaders() + { return headers; } // Deserilizes and processes given messagesString - private void processMessagesString(string messagesString) { - if (messagesString == "" || messagesString == null) { + private void ProcessMessagesString(string messagesString) + { + if (string.IsNullOrEmpty(messagesString)) + { return; } JObject messages = JObject.Parse(messagesString); - addMessages(messages); - processMessages(); + AddMessages(messages); + ProcessMessages(); } // Add list of messages to message queue - private void addMessages(JObject messages) { - if (messages == null) { + private void AddMessages(JObject messages) + { + if (messages == null) + { return; } int lowestMessageId = -1; - foreach (var message in messages) { + foreach (KeyValuePair message in messages) + { // Check if the messageId is lower than our current messageId int messageId = int.Parse(message.Key); - if (messageId == 0) { + if (messageId == 0) + { messageQueue.Add(messageId, message.Value); continue; } - if (messageId < currentMessageId) { + if (messageId < currentMessageId) + { continue; } // Keep track of the largest messageId in the list - if (messageId > largestMessageId) { + if (messageId > largestMessageId) + { largestMessageId = messageId; } // Keep track of the lowest messageId in the list - if (lowestMessageId == -1 || messageId < lowestMessageId) { + if (lowestMessageId == -1 || messageId < lowestMessageId) + { lowestMessageId = messageId; } // Check if the message exists in the queue, if not add it - if (!messageQueue.ContainsKey(messageId)) { + if (!messageQueue.ContainsKey(messageId)) + { messageQueue.Add(messageId, message.Value); } } // If the current messageId has never been set, set it to the current lowest - if (currentMessageId == -1) { + if (currentMessageId == -1) + { currentMessageId = lowestMessageId; } } // Process the message queue till we reach the end or a gap - private void processMessages() { + private void ProcessMessages() + { // Process all ordered messages in the order they appear - while (currentMessageId <= largestMessageId) { + while (currentMessageId <= largestMessageId) + { // Check if the next messageId exists - if (!messageQueue.ContainsKey(currentMessageId)) { + if (!messageQueue.ContainsKey(currentMessageId)) + { break; } // Process the message - mage.eventManager.emitEventList((JArray)messageQueue[currentMessageId]); + Mage.EventManager.EmitEventList((JArray)messageQueue[currentMessageId]); confirmIds.Add(currentMessageId.ToString()); messageQueue.Remove(currentMessageId); @@ -227,8 +262,9 @@ private void processMessages() { } // Finally emit any events that don't have an ID and thus don't need confirmation and lack order - if (messageQueue.ContainsKey(0)) { - mage.eventManager.emitEventList((JArray)messageQueue[0]); + if (messageQueue.ContainsKey(0)) + { + Mage.EventManager.EmitEventList((JArray)messageQueue[0]); messageQueue.Remove(0); } } diff --git a/Mage/MessageStream/TransportClient/LongPolling.cs b/Mage/MessageStream/TransportClient/LongPolling.cs index 51a2b0e..f521462 100644 --- a/Mage/MessageStream/TransportClient/LongPolling.cs +++ b/Mage/MessageStream/TransportClient/LongPolling.cs @@ -5,127 +5,165 @@ using Wizcorp.MageSDK.Log; using Wizcorp.MageSDK.Network.Http; -namespace Wizcorp.MageSDK.MageClient.Message.Client { - public class LongPolling : TransportClient { - private Mage mage { get { return Mage.Instance; } } - private Logger logger { get { return mage.logger("longpolling"); } } +namespace Wizcorp.MageSDK.MageClient.Message.Client +{ + public class LongPolling : TransportClient + { + private static Mage Mage + { + get { return Mage.Instance; } + } + + private static Logger Logger + { + get { return Mage.Logger("LongPolling"); } + } // Required functions for poll requests - private Func _getEndpoint; - private Func> _getHeaders; - private Action _processMessages; + private Func getEndpoint; + private Func> getHeaders; + private Action processMessages; // - HTTPRequest _currentRequest; + private HttpRequest currentRequest; // Required interval timer for polling delay - private int _errorInterval; - private Timer _intervalTimer; + private int errorInterval; + private Timer intervalTimer; // Constructor - public LongPolling(Func getEndpointFn, Func> getHeadersFn, Action processMessagesFn, int errorInterval = 5000) { - _getEndpoint = getEndpointFn; - _getHeaders = getHeadersFn; - _processMessages = processMessagesFn; - _errorInterval = errorInterval; + public LongPolling(Func getEndpointFn, Func> getHeadersFn, Action processMessagesFn, int errorInterval = 5000) + { + getEndpoint = getEndpointFn; + getHeaders = getHeadersFn; + processMessages = processMessagesFn; + this.errorInterval = errorInterval; } // Starts the poller - public override void start() { - if (_running == true) { + public override void Start() + { + if (_running) + { return; } - logger.debug("Starting"); + Logger.Debug("Starting"); _running = true; - requestLoop(); + RequestLoop(); } // Stops the poller - public override void stop() { + public override void Stop() + { _running = false; - logger.debug("Stopping..."); + Logger.Debug("Stopping..."); - if (_intervalTimer != null) { - _intervalTimer.Dispose(); - _intervalTimer = null; - } else { - logger.debug("Timer Stopped"); + if (intervalTimer != null) + { + intervalTimer.Dispose(); + intervalTimer = null; + } + else + { + Logger.Debug("Timer Stopped"); } - if (_currentRequest != null) { - _currentRequest.Abort(); - _currentRequest = null; - } else { - logger.debug("Connections Stopped"); + if (currentRequest != null) + { + currentRequest.Abort(); + currentRequest = null; + } + else + { + Logger.Debug("Connections Stopped"); } } // Queues the next poll request - private void queueNextRequest(int waitFor) { + private void QueueNextRequest(int waitFor) + { // Wait _requestInterval milliseconds till next poll - _intervalTimer = new Timer((object state) => { - requestLoop(); - }, null, waitFor, Timeout.Infinite); + intervalTimer = new Timer( + state => { + RequestLoop(); + }, + null, + waitFor, + Timeout.Infinite + ); } // Poller request function - private void requestLoop() { + private void RequestLoop() + { // Clear the timer - if (_intervalTimer != null) { - _intervalTimer.Dispose(); - _intervalTimer = null; + if (intervalTimer != null) + { + intervalTimer.Dispose(); + intervalTimer = null; } // Check if the poller should be running - if (_running == false) { - logger.debug("Stopped"); + if (_running == false) + { + Logger.Debug("Stopped"); return; } // Send poll request and wait for a response - string endpoint = _getEndpoint(); - logger.debug("Sending request: " + endpoint); - _currentRequest = HTTPRequest.Get(endpoint, _getHeaders(), mage.cookies, (Exception requestError, string responseString) => { - _currentRequest = null; + string endpoint = getEndpoint(); + Logger.Debug("Sending request: " + endpoint); + currentRequest = HttpRequest.Get(endpoint, getHeaders(), Mage.Cookies, (requestError, responseString) => { + currentRequest = null; // Ignore errors if we have been stopped - if (requestError != null && !_running) { - logger.debug("Stopped"); + if (requestError != null && !_running) + { + Logger.Debug("Stopped"); return; } - if (requestError != null) { - if (requestError is HTTPRequestException) { + if (requestError != null) + { + var requestHttpError = requestError as HttpRequestException; + if (requestHttpError != null) + { // Only log web exceptions if they aren't an empty response or gateway timeout - HTTPRequestException requestException = requestError as HTTPRequestException; - if (requestException.Status != 0 && requestException.Status != 504) { - logger.error("(" + requestException.Status.ToString() + ") " + requestError.Message); + if (requestHttpError.Status != 0 && requestHttpError.Status != 504) + { + Logger.Error("(" + requestHttpError.Status.ToString() + ") " + requestHttpError.Message); } - } else { - logger.error(requestError.ToString()); + } + else + { + Logger.Error(requestError.ToString()); } - queueNextRequest(_errorInterval); + QueueNextRequest(errorInterval); return; } // Call the message processer hook and re-call request loop function - try { - logger.verbose("Recieved response: " + responseString); - if (responseString != null) { - _processMessages(responseString); + try + { + Logger.Verbose("Recieved response: " + responseString); + if (responseString != null) + { + processMessages(responseString); } - requestLoop(); - } catch (Exception error) { - logger.error(error.ToString()); - queueNextRequest(_errorInterval); + RequestLoop(); + } + catch (Exception error) + { + Logger.Error(error.ToString()); + QueueNextRequest(errorInterval); } }); } diff --git a/Mage/MessageStream/TransportClient/ShortPolling.cs b/Mage/MessageStream/TransportClient/ShortPolling.cs index 346551e..3543c71 100644 --- a/Mage/MessageStream/TransportClient/ShortPolling.cs +++ b/Mage/MessageStream/TransportClient/ShortPolling.cs @@ -1,105 +1,130 @@ using System; -using System.Collections; using System.Collections.Generic; using System.Threading; using Wizcorp.MageSDK.Log; using Wizcorp.MageSDK.Network.Http; -namespace Wizcorp.MageSDK.MageClient.Message.Client { - public class ShortPolling : TransportClient { - private Mage mage { get { return Mage.Instance; } } - private Logger logger { get { return mage.logger("shortpolling"); } } +namespace Wizcorp.MageSDK.MageClient.Message.Client +{ + public class ShortPolling : TransportClient + { + private static Mage Mage + { + get { return Mage.Instance; } + } - // Whether or not the poller is working - private bool _running = false; + private static Logger Logger + { + get { return Mage.Logger("ShortPolling"); } + } // Required functions for poll requests - private Func _getEndpoint; - private Func> _getHeaders; - private Action _processMessages; + private Func getEndpoint; + private Func> getHeaders; + private Action processMessages; // Required interval timer for polling delay - private int _requestInterval; - private int _errorInterval; - private Timer _intervalTimer; + private int requestInterval; + private int errorInterval; + private Timer intervalTimer; // Constructor - public ShortPolling(Func getEndpointFn, Func> getHeadersFn, Action processMessagesFn, int requestInterval = 5000, int errorInterval = 5000) { - _getEndpoint = getEndpointFn; - _getHeaders = getHeadersFn; - _processMessages = processMessagesFn; - _requestInterval = requestInterval; - _errorInterval = errorInterval; + public ShortPolling(Func getEndpointFn, Func> getHeadersFn, Action processMessagesFn, int requestInterval = 5000, int errorInterval = 5000) + { + getEndpoint = getEndpointFn; + getHeaders = getHeadersFn; + processMessages = processMessagesFn; + this.requestInterval = requestInterval; + this.errorInterval = errorInterval; } // Starts the poller - public override void start() { - if (_running == true) { + public override void Start() + { + if (_running) + { return; } - logger.debug("Starting"); + Logger.Debug("Starting"); _running = true; - requestLoop(); + RequestLoop(); } // Stops the poller - public override void stop() { - if (_intervalTimer != null) { - _intervalTimer.Dispose(); - _intervalTimer = null; - logger.debug("Stopped"); - } else { - logger.debug("Stopping..."); + public override void Stop() + { + if (intervalTimer != null) + { + intervalTimer.Dispose(); + intervalTimer = null; + Logger.Debug("Stopped"); + } + else + { + Logger.Debug("Stopping..."); } _running = false; } // Queues the next poll request - private void queueNextRequest(int waitFor) { - // Wait _requestInterval milliseconds till next poll - _intervalTimer = new Timer((object state) => { - requestLoop(); - }, null, waitFor, Timeout.Infinite); + private void QueueNextRequest(int waitFor) + { + // Wait n milliseconds till next poll + intervalTimer = new Timer( + state => { + RequestLoop(); + }, + null, + waitFor, + Timeout.Infinite + ); } // Poller request function - private void requestLoop() { + private void RequestLoop() + { // Clear the timer - if (_intervalTimer != null) { - _intervalTimer.Dispose(); - _intervalTimer = null; + if (intervalTimer != null) + { + intervalTimer.Dispose(); + intervalTimer = null; } // Check if the poller should be running - if (_running == false) { - logger.debug("Stopped"); + if (_running == false) + { + Logger.Debug("Stopped"); return; } // Send poll request and wait for a response - string endpoint = _getEndpoint(); - logger.debug("Sending request: " + endpoint); - HTTPRequest.Get(endpoint, _getHeaders(), mage.cookies, (Exception requestError, string responseString) => { - if (requestError != null) { - logger.error(requestError.ToString()); - queueNextRequest(_errorInterval); + string endpoint = getEndpoint(); + Logger.Debug("Sending request: " + endpoint); + HttpRequest.Get(endpoint, getHeaders(), Mage.Cookies, (requestError, responseString) => { + if (requestError != null) + { + Logger.Error(requestError.ToString()); + QueueNextRequest(errorInterval); return; } // Call the message processer hook and queue the next request - try { - _processMessages(responseString); - queueNextRequest(_requestInterval); - } catch (Exception error) { - logger.data(responseString).error(error.ToString()); - queueNextRequest(_errorInterval); + try + { + processMessages(responseString); + QueueNextRequest(requestInterval); + } + catch (Exception error) + { + Logger.Data(responseString).Error(error.ToString()); + QueueNextRequest(errorInterval); } }); } diff --git a/Mage/MessageStream/TransportClient/TransportClient.cs b/Mage/MessageStream/TransportClient/TransportClient.cs index 9ba9c96..7c91f95 100644 --- a/Mage/MessageStream/TransportClient/TransportClient.cs +++ b/Mage/MessageStream/TransportClient/TransportClient.cs @@ -1,16 +1,11 @@ -using System; - -namespace Wizcorp.MageSDK.MageClient.Message.Client { - public enum TransportType { - SHORTPOLLING, - LONGPOLLING - } - - public abstract class TransportClient { +namespace Wizcorp.MageSDK.MageClient.Message.Client +{ + public abstract class TransportClient + { protected bool _running; public bool running { get { return _running; } } - public abstract void stop(); - public abstract void start(); + public abstract void Stop(); + public abstract void Start(); } } diff --git a/Mage/MessageStream/TransportClient/TransportType.cs b/Mage/MessageStream/TransportClient/TransportType.cs new file mode 100644 index 0000000..39d907c --- /dev/null +++ b/Mage/MessageStream/TransportClient/TransportType.cs @@ -0,0 +1,8 @@ +namespace Wizcorp.MageSDK.MageClient.Message.Client +{ + public enum TransportType + { + SHORTPOLLING, + LONGPOLLING + } +} diff --git a/Mage/Module.cs b/Mage/Module.cs index 0e29be0..460aeff 100644 --- a/Mage/Module.cs +++ b/Mage/Module.cs @@ -6,105 +6,135 @@ using Wizcorp.MageSDK.Log; using Wizcorp.MageSDK.Utils; -namespace Wizcorp.MageSDK.MageClient { - public class UsercommandStatus { - public bool done = false; - public Exception error = null; - public JToken result = null; - } - +namespace Wizcorp.MageSDK.MageClient +{ - public class Module : Singleton where T : class, new() { + public class Module : Singleton where T : class, new() + { // - protected Mage mage { get { return Mage.Instance; } } - protected Logger logger { get { return mage.logger(this.GetType().Name); } } + protected Mage Mage + { + get { return Mage.Instance; } + } + + protected Logger Logger + { + get { return Mage.Logger(GetType().Name); } + } // - protected virtual List staticTopics { get { return null; } } - public JToken staticData; - public void setupStaticData(Action cb) { - logger.info("Setting up static data"); + protected virtual List StaticTopics + { + get { return null; } + } + + public JToken StaticData; - if (staticTopics == null) { + public void SetupStaticData(Action cb) + { + Logger.Info("Setting up static data"); + + if (StaticTopics == null) + { cb(null); return; } - JObject queries = new JObject(); - for (int i = 0; i < staticTopics.Count; i++) { - string topic = staticTopics[i]; + var queries = new JObject(); + for (var i = 0; i < StaticTopics.Count; i++) + { + string topic = StaticTopics[i]; - JObject query = new JObject(); - query.Add("topic", new JValue(topic)); - query.Add("index", new JObject()); + var query = new JObject { + {"topic", new JValue(topic)}, + {"index", new JObject()} + }; queries.Add(topic, query); } - staticData = null; - mage.archivist.mget(queries, null, (Exception error, JToken data) => { - if (error != null) { + StaticData = null; + Mage.Archivist.MGet(queries, null, (error, data) => { + if (error != null) + { cb(error); return; } - staticData = data; + StaticData = data; cb(null); }); } // - protected virtual string commandPrefix { get { return null; } } - protected virtual List commands { get { return null; } } + protected virtual string CommandPrefix + { + get { return null; } + } + + protected virtual List Commands + { + get { return null; } + } + private Dictionary>> commandHandlerActions; - private Dictionary> commandHandlerFuncs; + private Dictionary> commandHandlerFuncs; - public void command(string commandName, JObject arguments, Action cb) { + public void Command(string commandName, JObject arguments, Action cb) + { commandHandlerActions[commandName](arguments, cb); } - public UsercommandStatus command(string commandName, JObject arguments) { + public UserCommandStatus Command(string commandName, JObject arguments) + { return commandHandlerFuncs[commandName](arguments); } - private void registerCommand(string command) { - commandHandlerActions.Add(command, (JObject arguments, Action commandCb) => { - mage.commandCenter.SendCommand(commandPrefix + "." + command, arguments, (Exception error, JToken result) => { - try { + private void RegisterCommand(string command) + { + commandHandlerActions.Add(command, (arguments, commandCb) => { + Mage.CommandCenter.SendCommand(CommandPrefix + "." + command, arguments, (error, result) => { + try + { commandCb(error, result); - } catch (Exception callbackError) { - logger.data(callbackError).critical("Uncaught exception:"); + } + catch (Exception callbackError) + { + Logger.Data(callbackError).Critical("Uncaught exception:"); } }); }); - commandHandlerFuncs.Add(command, (JObject arguments) => { - UsercommandStatus commandStatus = new UsercommandStatus(); + commandHandlerFuncs.Add(command, arguments => { + var commandStatus = new UserCommandStatus(); - mage.commandCenter.SendCommand(commandPrefix + "." + command, arguments, (Exception error, JToken result) => { - commandStatus.error = error; - commandStatus.result = result; - commandStatus.done = true; + Mage.CommandCenter.SendCommand(CommandPrefix + "." + command, arguments, (error, result) => { + commandStatus.Error = error; + commandStatus.Result = result; + commandStatus.Done = true; }); return commandStatus; }); } - public void setupUsercommands(Action cb) { - logger.info("Setting up usercommands"); + public void SetupUsercommands(Action cb) + { + Logger.Info("Setting up usercommands"); commandHandlerActions = new Dictionary>>(); - commandHandlerFuncs = new Dictionary>(); + commandHandlerFuncs = new Dictionary>(); - if (commands == null) { + if (Commands == null) + { cb(null); return; } - foreach (string command in commands) { - registerCommand(command); + foreach (string command in Commands) + { + RegisterCommand(command); } cb(null); diff --git a/Mage/Session.cs b/Mage/Session.cs index 12d3774..6663cd9 100644 --- a/Mage/Session.cs +++ b/Mage/Session.cs @@ -1,45 +1,54 @@ using System.Collections.Generic; -using Newtonsoft.Json.Linq; +namespace Wizcorp.MageSDK.MageClient +{ + public class Session + { + private Mage Mage + { + get { return Mage.Instance; } + } -namespace Wizcorp.MageSDK.MageClient { - public class Session { - private Mage mage { get { return Mage.Instance; } } // private string sessionKey; private string actorId; + // - public Session() { - mage.eventManager.on("session.set", (object sender, JToken session) => { + public Session() + { + Mage.EventManager.On("session.set", (sender, session) => { actorId = session["actorId"].ToString(); sessionKey = session["key"].ToString(); }); - mage.eventManager.on("session.unset", (object sender, JToken reason) => { + Mage.EventManager.On("session.unset", (sender, reason) => { actorId = null; sessionKey = null; }); - mage.commandCenter.preSerialiseHook += (CommandBatch commandBatch) => { - if (!string.IsNullOrEmpty(sessionKey)) { + Mage.CommandCenter.preSerialiseHook += (commandBatch) => { + if (!string.IsNullOrEmpty(sessionKey)) + { Dictionary sessionHeader = new Dictionary(); sessionHeader.Add("name", "mage.session"); sessionHeader.Add("key", sessionKey); - commandBatch.batchHeaders.Add(sessionHeader); + commandBatch.BatchHeaders.Add(sessionHeader); } }; } // - public string GetSessionKey() { + public string GetSessionKey() + { return sessionKey; } // - public string GetActorId() { + public string GetActorId() + { return actorId; } } diff --git a/Mage/UserCommandStatus.cs b/Mage/UserCommandStatus.cs new file mode 100644 index 0000000..16636c3 --- /dev/null +++ b/Mage/UserCommandStatus.cs @@ -0,0 +1,13 @@ +using System; + +using Newtonsoft.Json.Linq; + +namespace Wizcorp.MageSDK.MageClient +{ + public class UserCommandStatus + { + public bool Done = false; + public Exception Error = null; + public JToken Result = null; + } +} diff --git a/Newtonsoft.Json.dll b/Newtonsoft.Json.dll index aa190de..664cd62 100755 Binary files a/Newtonsoft.Json.dll and b/Newtonsoft.Json.dll differ diff --git a/Newtonsoft.Json.dll.mdb b/Newtonsoft.Json.dll.mdb new file mode 100644 index 0000000..9e0f14c Binary files /dev/null and b/Newtonsoft.Json.dll.mdb differ diff --git a/Singleton/MonoSingleton.cs b/Singleton/MonoSingleton.cs index ec841f1..6855fee 100644 --- a/Singleton/MonoSingleton.cs +++ b/Singleton/MonoSingleton.cs @@ -1,40 +1,49 @@ using UnityEngine; -namespace Wizcorp.MageSDK.Utils { - public class MonoSingleton : MonoBehaviour where T : MonoBehaviour { +namespace Wizcorp.MageSDK.Utils +{ + public class MonoSingleton : MonoBehaviour where T : MonoBehaviour + { // Instance functions - protected static T _Instance; - public static T Instance { - get { - if (_Instance == null) { + protected static T instance; + public static T Instance + { + get + { + if (instance == null) + { Instantiate(); } - return _Instance; + return instance; } } // Instantiation function if you need to pre-instantiate rather than on demand - public static void Instantiate() { - if (_Instance != null) { + public static void Instantiate() + { + if (instance != null) + { return; } - GameObject newObject = new GameObject(typeof(T).Name); - GameObject.DontDestroyOnLoad(newObject); + var newObject = new GameObject(typeof(T).Name); + DontDestroyOnLoad(newObject); - _Instance = newObject.AddComponent(); + instance = newObject.AddComponent(); } // Use this for initialization before any start methods are called - protected virtual void Awake() { - if (_Instance != null) { - GameObject.DestroyImmediate(gameObject); + protected virtual void Awake() + { + if (instance != null) + { + DestroyImmediate(gameObject); return; } - _Instance = (T)(object)this; - GameObject.DontDestroyOnLoad(gameObject); + instance = (T)(object)this; + DontDestroyOnLoad(gameObject); } } } diff --git a/Singleton/SceneInstance.cs b/Singleton/SceneInstance.cs index 1e62c99..728aed2 100644 --- a/Singleton/SceneInstance.cs +++ b/Singleton/SceneInstance.cs @@ -1,19 +1,26 @@ using UnityEngine; -namespace Wizcorp.MageSDK.Utils { - public class SceneInstance : MonoBehaviour where T : class { +namespace Wizcorp.MageSDK.Utils +{ + public class SceneInstance : MonoBehaviour where T : class + { // - protected static T _Instance = null; - public static T Instance { get { return _Instance; } } + protected static T instance; + public static T Instance + { + get { return instance; } + } // Use this for initialization before any start methods are called - protected virtual void Awake() { - _Instance = (T)(object)this; + protected virtual void Awake() + { + instance = (T)(object)this; } // Use this for destruction - protected virtual void OnDestroy() { - _Instance = null; + protected virtual void OnDestroy() + { + instance = null; } } } diff --git a/Singleton/Singleton.cs b/Singleton/Singleton.cs index 2bae7c4..bbba51c 100644 --- a/Singleton/Singleton.cs +++ b/Singleton/Singleton.cs @@ -1,22 +1,18 @@ -using UnityEngine; - -namespace Wizcorp.MageSDK.Utils { - public class Singleton where T : class, new() { +namespace Wizcorp.MageSDK.Utils +{ + public class Singleton where T : class, new() + { // Instance functions - private static T _Instance; - public static T Instance { - get { - if (_Instance == null) { - _Instance = new T(); - } - - return _Instance; - } + private static T instance; + public static T Instance + { + get { return instance ?? (instance = new T()); } } // Hack which makes sure the _instance property is set during the T class constructor - public Singleton() { - _Instance = (T)(object)this; + protected Singleton() + { + instance = (T)(object)this; } } } diff --git a/Tomes/Tome.cs b/Tomes/Tome.cs index 16007ea..261af76 100644 --- a/Tomes/Tome.cs +++ b/Tomes/Tome.cs @@ -3,16 +3,20 @@ using Newtonsoft.Json.Linq; -namespace Wizcorp.MageSDK.Tomes { - public class Tome { +namespace Wizcorp.MageSDK.Tomes +{ + public class Tome + { public delegate void OnChanged(JToken oldValue); public delegate void OnDestroy(); public delegate void OnAdd(JToken key); public delegate void OnDel(JToken key); // - public static JToken Conjure(JToken data, JToken root = null) { - switch (data.Type) { + public static JToken Conjure(JToken data, JToken root = null) + { + switch (data.Type) + { case JTokenType.Array: return new TomeArray((JArray)data, root); case JTokenType.Object: @@ -23,23 +27,27 @@ public static JToken Conjure(JToken data, JToken root = null) { } // - public static void Destroy(JToken data) { - switch (data.Type) { + public static void Destroy(JToken data) + { + switch (data.Type) + { case JTokenType.Array: - (data as TomeArray).Destroy(); + ((TomeArray)data).Destroy(); break; case JTokenType.Object: - (data as TomeObject).Destroy(); + ((TomeObject)data).Destroy(); break; default: - (data as TomeValue).Destroy(); + ((TomeValue)data).Destroy(); break; } } // - public static JToken PathValue(JToken value, JArray paths) { - foreach (JToken path in paths) { + public static JToken PathValue(JToken value, JArray paths) + { + foreach (JToken path in paths) + { value = PathValue(value, path); } @@ -47,8 +55,10 @@ public static JToken PathValue(JToken value, JArray paths) { } // - public static JToken PathValue(JToken value, List paths) { - foreach (string path in paths) { + public static JToken PathValue(JToken value, List paths) + { + foreach (string path in paths) + { value = PathValue(value, path); } @@ -56,8 +66,10 @@ public static JToken PathValue(JToken value, List paths) { } // - public static JToken PathValue(JToken value, JToken key) { - if (value.Type == JTokenType.Array) { + public static JToken PathValue(JToken value, JToken key) + { + if (value.Type == JTokenType.Array) + { return value[(int)key]; } @@ -65,8 +77,10 @@ public static JToken PathValue(JToken value, JToken key) { } // - public static JToken PathValue(JToken value, string key) { - if (value.Type == JTokenType.Array) { + public static JToken PathValue(JToken value, string key) + { + if (value.Type == JTokenType.Array) + { return value[int.Parse(key)]; } @@ -74,18 +88,22 @@ public static JToken PathValue(JToken value, string key) { } // - public static void EmitParentChange(JToken parent) { - switch (parent.Type) { + public static void EmitParentChange(JToken parent) + { + switch (parent.Type) + { case JTokenType.Array: - TomeArray parentArray = parent as TomeArray; - if (parentArray.onChanged != null) { - parentArray.onChanged.Invoke(null); + var parentArray = (TomeArray)parent; + if (parentArray.OnChanged != null) + { + parentArray.OnChanged.Invoke(null); } break; case JTokenType.Object: - TomeObject parentObject = parent as TomeObject; - if (parentObject.onChanged != null) { - parentObject.onChanged.Invoke(null); + var parentObject = (TomeObject)parent; + if (parentObject.OnChanged != null) + { + parentObject.OnChanged.Invoke(null); } break; case JTokenType.Property: @@ -97,26 +115,32 @@ public static void EmitParentChange(JToken parent) { } // - public static void ApplyDiff(JToken root, JArray operations) { - foreach (JObject operation in operations) { - try { + public static void ApplyDiff(JToken root, JArray operations) + { + foreach (JObject operation in operations) + { + try + { JToken value = PathValue(root, (JArray)operation["chain"]); string op = operation["op"].ToString(); JToken val = operation["val"]; - switch (value.Type) { + switch (value.Type) + { case JTokenType.Array: - (value as TomeArray).ApplyOperation(op, val, root); + ((TomeArray)value).ApplyOperation(op, val, root); break; case JTokenType.Object: - (value as TomeObject).ApplyOperation(op, val, root); + ((TomeObject)value).ApplyOperation(op, val, root); break; default: - (value as TomeValue).ApplyOperation(op, val); + ((TomeValue)value).ApplyOperation(op, val); break; } - } catch (Exception diffError) { + } + catch (Exception diffError) + { // TODO: NEED TO DECIDE IF TOMES SHOULD BE STANDALONE OR INSIDE MAGE. // e.g. should it depend on mage.logger or UnityEngine.Debug for logging? UnityEngine.Debug.LogError("Failed to apply diff operation:"); @@ -124,7 +148,7 @@ public static void ApplyDiff(JToken root, JArray operations) { UnityEngine.Debug.LogError(diffError); UnityEngine.Debug.LogError(root); UnityEngine.Debug.LogError(PathValue(root, (JArray)operation["chain"])); - throw diffError; + throw; } } } diff --git a/Tomes/TomeArray.cs b/Tomes/TomeArray.cs index feac101..06dea97 100644 --- a/Tomes/TomeArray.cs +++ b/Tomes/TomeArray.cs @@ -1,134 +1,160 @@ using System; +using System.Collections.Generic; using Newtonsoft.Json.Linq; using Wizcorp.MageSDK.MageClient; -namespace Wizcorp.MageSDK.Tomes { - public class TomeArray : JArray { +namespace Wizcorp.MageSDK.Tomes +{ + public class TomeArray : JArray + { // - public Tome.OnChanged onChanged; - public Tome.OnDestroy onDestroy; - public Tome.OnAdd onAdd; - public Tome.OnDel onDel; + public Tome.OnChanged OnChanged; + public Tome.OnDestroy OnDestroy; + public Tome.OnAdd OnAdd; + public Tome.OnDel OnDel; // private JToken root; - // - public TomeArray(JArray data, JToken _root) { + public TomeArray(JArray data, JToken root) + { // - root = _root; - if (root == null) { - root = this; + this.root = root; + if (this.root == null) + { + this.root = this; } // - for (int i = 0; i < data.Count; i += 1) { - this.Add(Tome.Conjure(data[i], root)); + for (var i = 0; i < data.Count; i += 1) + { + Add(Tome.Conjure(data[i], root)); } // - onChanged += EmitToParents; - onAdd += EmitChanged; - onDel += EmitChanged; + OnChanged += EmitToParents; + OnAdd += EmitChanged; + OnDel += EmitChanged; } // - private void EmitToParents(JToken oldValue) { - if (this != root) { + private void EmitToParents(JToken oldValue) + { + if (this != root) + { Tome.EmitParentChange(Parent); } } // - private void EmitChanged(JToken key) { - if (onChanged != null) { - onChanged.Invoke(null); + private void EmitChanged(JToken key) + { + if (OnChanged != null) + { + OnChanged.Invoke(null); } } - // - public void Assign(JToken newValue) { - lock ((object)this) { - switch (newValue.Type) { + public void Assign(JToken newValue) + { + lock ((object)this) + { + switch (newValue.Type) + { case JTokenType.Array: - TomeArray newTomeArray = new TomeArray((JArray)newValue, root); - this.Replace(newTomeArray); + var newTomeArray = new TomeArray((JArray)newValue, root); + Replace(newTomeArray); - if (this.Parent == null) { - // If replace was successfuly move over event handlers and call new onChanged handler + if (Parent == null) + { + // If replace was successfuly move over event handlers and call new OnChanged handler // The instance in which replace would not be successful, is when the old and new values are the same - onChanged -= EmitToParents; - onChanged += newTomeArray.onChanged; - newTomeArray.onChanged = onChanged; - newTomeArray.onDestroy = onDestroy; - onAdd -= EmitChanged; - onAdd += newTomeArray.onAdd; - newTomeArray.onAdd = onAdd; - onDel -= EmitChanged; - onDel += newTomeArray.onDel; - newTomeArray.onDel = onDel; - - if (newTomeArray.onChanged != null) { - newTomeArray.onChanged.Invoke(null); + OnChanged -= EmitToParents; + OnChanged += newTomeArray.OnChanged; + newTomeArray.OnChanged = OnChanged; + newTomeArray.OnDestroy = OnDestroy; + OnAdd -= EmitChanged; + OnAdd += newTomeArray.OnAdd; + newTomeArray.OnAdd = OnAdd; + OnDel -= EmitChanged; + OnDel += newTomeArray.OnDel; + newTomeArray.OnDel = OnDel; + + if (newTomeArray.OnChanged != null) + { + newTomeArray.OnChanged.Invoke(null); } - } else { - // Otherwise call original onChanged handler - if (onChanged != null) { - onChanged.Invoke(null); + } + else + { + // Otherwise call original OnChanged handler + if (OnChanged != null) + { + OnChanged.Invoke(null); } } break; case JTokenType.Object: - TomeObject newTomeObject = new TomeObject((JObject)newValue, root); - this.Replace(newTomeObject); + var newTomeObject = new TomeObject((JObject)newValue, root); + Replace(newTomeObject); - if (this.Parent == null) { - // If replace was successfuly move over event handlers and call new onChanged handler + if (Parent == null) + { + // If replace was successfuly move over event handlers and call new OnChanged handler // The instance in which replace would not be successful, is when the old and new values are the same - onChanged -= EmitToParents; - onChanged += newTomeObject.onChanged; - newTomeObject.onChanged = onChanged; - newTomeObject.onDestroy = onDestroy; - onAdd -= EmitChanged; - onAdd += newTomeObject.onAdd; - newTomeObject.onAdd = onAdd; - onDel -= EmitChanged; - onDel += newTomeObject.onDel; - newTomeObject.onDel = onDel; - - if (newTomeObject.onChanged != null) { - newTomeObject.onChanged.Invoke(null); + OnChanged -= EmitToParents; + OnChanged += newTomeObject.OnChanged; + newTomeObject.OnChanged = OnChanged; + newTomeObject.OnDestroy = OnDestroy; + OnAdd -= EmitChanged; + OnAdd += newTomeObject.OnAdd; + newTomeObject.OnAdd = OnAdd; + OnDel -= EmitChanged; + OnDel += newTomeObject.OnDel; + newTomeObject.OnDel = OnDel; + + if (newTomeObject.OnChanged != null) + { + newTomeObject.OnChanged.Invoke(null); } - } else { - // Otherwise call original onChanged handler - if (onChanged != null) { - onChanged.Invoke(null); + } + else + { + // Otherwise call original OnChanged handler + if (OnChanged != null) + { + OnChanged.Invoke(null); } } break; default: - TomeValue newTomeValue = new TomeValue((JValue)newValue, root); - this.Replace(newTomeValue); + var newTomeValue = new TomeValue((JValue)newValue, root); + Replace(newTomeValue); - if (this.Parent == null) { - // If replace was successfuly move over event handlers and call new onChanged handler + if (Parent == null) + { + // If replace was successfuly move over event handlers and call new OnChanged handler // The instance in which replace would not be successful, is when the old and new values are the same - onChanged -= EmitToParents; - onChanged += newTomeValue.onChanged; - newTomeValue.onChanged = onChanged; - newTomeValue.onDestroy = onDestroy; - - if (newTomeValue.onChanged != null) { - newTomeValue.onChanged.Invoke(null); + OnChanged -= EmitToParents; + OnChanged += newTomeValue.OnChanged; + newTomeValue.OnChanged = OnChanged; + newTomeValue.OnDestroy = OnDestroy; + + if (newTomeValue.OnChanged != null) + { + newTomeValue.OnChanged.Invoke(null); } - } else { - // Otherwise call original onChanged handler - if (onChanged != null) { - onChanged.Invoke(null); + } + else + { + // Otherwise call original OnChanged handler + if (OnChanged != null) + { + OnChanged.Invoke(null); } } break; @@ -137,93 +163,122 @@ public void Assign(JToken newValue) { } // - public void Destroy() { - lock ((object)this) { - foreach (JToken value in this) { + public void Destroy() + { + lock ((object)this) + { + foreach (JToken value in this) + { Tome.Destroy(value); } - if (onDestroy != null) { - onDestroy.Invoke(); + if (OnDestroy != null) + { + OnDestroy.Invoke(); } - onChanged = null; - onDestroy = null; - onAdd = null; - onDel = null; + OnChanged = null; + OnDestroy = null; + OnAdd = null; + OnDel = null; } } // - public void Set(int index, JToken value) { - lock ((object)this) { + public void Set(int index, JToken value) + { + lock ((object)this) + { // Make sure the property exists, filling in missing indexes - if (this.Count <= index) { - while (this.Count < index) { - this.Add(Tome.Conjure(JValue.CreateNull(), root)); + if (Count <= index) + { + while (Count < index) + { + Add(Tome.Conjure(JValue.CreateNull(), root)); } - this.Add(Tome.Conjure(value, root)); - if (onAdd != null) { - onAdd.Invoke(index); + Add(Tome.Conjure(value, root)); + if (OnAdd != null) + { + OnAdd.Invoke(index); } return; } // Assign the property JToken property = this[index]; - switch (property.Type) { + switch (property.Type) + { case JTokenType.Array: - (property as TomeArray).Assign(value); + ((TomeArray)property).Assign(value); break; case JTokenType.Object: - (property as TomeObject).Assign(value); + ((TomeObject)property).Assign(value); break; default: - if ((property as TomeValue) == null) { - Mage.Instance.logger("Tomes").data(property).error("property is not a tome value: " + index.ToString()); + var tomeValue = property as TomeValue; + if (tomeValue == null) + { + Mage.Instance.Logger("Tomes").Data(property).Error("property is not a tome value: " + index.ToString()); UnityEngine.Debug.Log(this); } - (property as TomeValue).Assign(value); + else + { + tomeValue.Assign(value); + } break; } } } // - public void Del(int index) { - lock ((object)this) { + public void Del(int index) + { + lock ((object)this) + { JToken property = this[index]; - switch (property.Type) { + switch (property.Type) + { case JTokenType.Array: - (property as TomeArray).Destroy(); + ((TomeArray)property).Destroy(); break; case JTokenType.Object: - (property as TomeObject).Destroy(); + ((TomeObject)property).Destroy(); break; default: - if ((property as TomeValue) == null) { - Mage.Instance.logger("Tomes").data(property).error("property is not a tome value:" + index.ToString()); + var tomeValue = property as TomeValue; + if (tomeValue == null) + { + Mage.Instance.Logger("Tomes").Data(property).Error("property is not a tome value:" + index.ToString()); UnityEngine.Debug.Log(this); } - (property as TomeValue).Destroy(); + else + { + tomeValue.Destroy(); + } break; } this[index].Replace(JValue.CreateNull()); - if (onDel != null) { - onDel.Invoke(index); + if (OnDel != null) + { + OnDel.Invoke(index); } } } // - public void Move(int fromKey, JToken newParent, JToken newKey) { - lock ((object)this) { - if (newParent.Type == JTokenType.Array) { - (newParent as TomeArray).Set((int)newKey, this[fromKey]); - } else { - (newParent as TomeObject).Set((string)newKey, this[fromKey]); + public void Move(int fromKey, JToken newParent, JToken newKey) + { + lock ((object)this) + { + if (newParent.Type == JTokenType.Array) + { + ((TomeArray)newParent).Set((int)newKey, this[fromKey]); + } + else + { + ((TomeObject)newParent).Set((string)newKey, this[fromKey]); } Del(fromKey); @@ -231,8 +286,10 @@ public void Move(int fromKey, JToken newParent, JToken newKey) { } // - public void Rename(int wasKey, int isKey) { - lock ((object)this) { + public void Rename(int wasKey, int isKey) + { + lock ((object)this) + { JToken wasValue = this[wasKey]; Del(wasKey); Set(isKey, wasValue); @@ -240,39 +297,49 @@ public void Rename(int wasKey, int isKey) { } // - public void Swap(int firstKey, JToken secondParent, JToken secondKey) { - lock ((object)this) { + public void Swap(int firstKey, JToken secondParent, JToken secondKey) + { + lock ((object)this) + { JToken secondValue; - if (secondParent.Type == JTokenType.Array) { + if (secondParent.Type == JTokenType.Array) + { secondValue = secondParent[(int)secondKey]; secondParent[(int)secondKey].Replace(this[firstKey]); - } else { + } + else + { secondValue = secondParent[(string)secondKey]; secondParent[(string)secondKey].Replace(this[firstKey]); } this[firstKey].Replace(secondValue); - if (onChanged != null) { - onChanged.Invoke(null); + if (OnChanged != null) + { + OnChanged.Invoke(null); } } } // - public void Push(JToken item) { - lock ((object)this) { - this.Set(this.Count, item); + public void Push(JToken item) + { + lock ((object)this) + { + Set(Count, item); } } // NOTE: Tome behavior for a del operation is to replace values with null. // However a pop operation does in fact remove the item as well as // firing the del event. Thus we do both below. - public JToken Pop() { - lock ((object)this) { - JToken last = this[this.Count - 1]; - this.Del(this.Count - 1); - this.Last.Remove(); + public JToken Pop() + { + lock ((object)this) + { + JToken last = this[Count - 1]; + Del(Count - 1); + Last.Remove(); return last; } } @@ -280,45 +347,58 @@ public JToken Pop() { // NOTE: Tome behavior for a del operation is to replace values with null. // However a shift operation does in fact remove the item as well as // firing the del event. Thus we do both below. - public JToken Shift() { - lock ((object)this) { + public JToken Shift() + { + lock ((object)this) + { JToken first = this[0]; - this.Del(0); - this.First.Remove(); + Del(0); + First.Remove(); return first; } } // - public void UnShift(JToken item) { - lock ((object)this) { - this.AddFirst(Tome.Conjure(item, root)); - if (onAdd != null) { - onAdd.Invoke(0); + public void UnShift(JToken item) + { + lock ((object)this) + { + AddFirst(Tome.Conjure(item, root)); + if (OnAdd != null) + { + OnAdd.Invoke(0); } } } // - public void Reverse() { - lock ((object)this) { - JArray oldOrder = new JArray(this as JArray); - for (int i = oldOrder.Count; i > 0; i -= 1) { + public void Reverse() + { + lock ((object)this) + { + var oldOrder = new JArray(this); + for (int i = oldOrder.Count; i > 0; i -= 1) + { this[oldOrder.Count - i].Replace(oldOrder[i - 1]); } - if (onChanged != null) { - onChanged.Invoke(null); + if (OnChanged != null) + { + OnChanged.Invoke(null); } } } // - public void Splice(int index, int deleteCount, JArray insertItems) { - lock ((object)this) { + public void Splice(int index, int deleteCount, JArray insertItems) + { + lock ((object)this) + { // Delete given item count starting at given index - for (int delI = index + deleteCount - 1; delI >= index; delI -= 1) { - if (delI > this.Count - 1) { + for (int delI = index + deleteCount - 1; delI >= index; delI -= 1) + { + if (delI > Count - 1) + { continue; } @@ -327,11 +407,13 @@ public void Splice(int index, int deleteCount, JArray insertItems) { } // Insert given items starting at given index - for (int addI = 0; addI < insertItems.Count; addI += 1) { + for (var addI = 0; addI < insertItems.Count; addI += 1) + { int insertI = index + addI; - this.Insert(insertI, Tome.Conjure(insertItems[addI])); - if (onAdd != null) { - onAdd.Invoke(insertI); + Insert(insertI, Tome.Conjure(insertItems[addI])); + if (OnAdd != null) + { + OnAdd.Invoke(insertI); } } } @@ -339,11 +421,15 @@ public void Splice(int index, int deleteCount, JArray insertItems) { // We implement this as when using JArray.IndexOf(JToken) it compares the reference but not the value. - public int IndexOf(string lookFor) { - lock ((object)this) { - for (int i = 0; i < this.Count; i += 1) { + public int IndexOf(string lookFor) + { + lock ((object)this) + { + for (var i = 0; i < Count; i += 1) + { JToken value = this[i]; - if (value.Type == JTokenType.String && (string)value == lookFor) { + if (value.Type == JTokenType.String && (string)value == lookFor) + { return i; } } @@ -354,9 +440,12 @@ public int IndexOf(string lookFor) { // - public void ApplyOperation(string op, JToken val, JToken root) { - lock ((object)this) { - switch (op) { + public void ApplyOperation(string op, JToken val, JToken root) + { + lock ((object)this) + { + switch (op) + { case "assign": Assign(val); break; @@ -370,29 +459,31 @@ public void ApplyOperation(string op, JToken val, JToken root) { break; case "move": - int fromKey = (int)val["key"]; + var fromKey = (int)val["key"]; JToken newParent = Tome.PathValue(root, val["newParent"] as JArray); JToken toKey = (val["newKey"] != null) ? val["newKey"] : new JValue(fromKey); Move(fromKey, newParent, toKey); break; case "rename": - foreach (var property in val as JObject) { + foreach (KeyValuePair property in (JObject)val) + { int wasKey = int.Parse(property.Key); - int isKey = (int)property.Value; + var isKey = (int)property.Value; Rename(wasKey, isKey); } break; case "swap": - int firstKey = (int)val["key"]; + var firstKey = (int)val["key"]; JToken secondParent = Tome.PathValue(root, val["newParent"] as JArray); JToken secondKey = (val["newKey"] != null) ? val["newKey"] : new JValue(firstKey); Swap(firstKey, secondParent, secondKey); break; case "push": - foreach (JToken item in val as JArray) { + foreach (JToken item in (JArray)val) + { Push(item); } break; @@ -406,8 +497,9 @@ public void ApplyOperation(string op, JToken val, JToken root) { break; case "unshift": - JArray unshiftItems = val as JArray; - for (int i = unshiftItems.Count; i > 0; i -= 1) { + var unshiftItems = val as JArray; + for (int i = unshiftItems.Count; i > 0; i -= 1) + { UnShift(unshiftItems[i - 1]); } break; @@ -417,10 +509,10 @@ public void ApplyOperation(string op, JToken val, JToken root) { break; case "splice": - int index = (int)val[0]; - int deleteCount = (int)val[1]; + var index = (int)val[0]; + var deleteCount = (int)val[1]; - JArray items = new JArray(val as JArray); + var items = new JArray(val as JArray); items.First.Remove(); items.First.Remove(); diff --git a/Tomes/TomeObject.cs b/Tomes/TomeObject.cs index 92551f7..e2071bf 100644 --- a/Tomes/TomeObject.cs +++ b/Tomes/TomeObject.cs @@ -5,131 +5,158 @@ using Wizcorp.MageSDK.MageClient; -namespace Wizcorp.MageSDK.Tomes { - public class TomeObject : JObject { +namespace Wizcorp.MageSDK.Tomes +{ + public class TomeObject : JObject + { // - public Tome.OnChanged onChanged; - public Tome.OnDestroy onDestroy; - public Tome.OnAdd onAdd; - public Tome.OnDel onDel; + public Tome.OnChanged OnChanged; + public Tome.OnDestroy OnDestroy; + public Tome.OnAdd OnAdd; + public Tome.OnDel OnDel; // private JToken root; // - public TomeObject(JObject data, JToken _root) { + public TomeObject(JObject data, JToken root) + { // - root = _root; - if (root == null) { - root = this; + this.root = root; + if (this.root == null) + { + this.root = this; } // - foreach (JProperty property in data.Properties()) { - this.Add(property.Name, Tome.Conjure(property.Value, root)); + foreach (JProperty property in data.Properties()) + { + Add(property.Name, Tome.Conjure(property.Value, root)); } // - onChanged += EmitToParents; - onAdd += EmitChanged; - onDel += EmitChanged; + OnChanged += EmitToParents; + OnAdd += EmitChanged; + OnDel += EmitChanged; } // - private void EmitToParents(JToken oldValue) { - if (this != root) { + private void EmitToParents(JToken oldValue) + { + if (this != root) + { Tome.EmitParentChange(Parent); } } // - private void EmitChanged(JToken key) { - if (onChanged != null) { - onChanged.Invoke(null); + private void EmitChanged(JToken key) + { + if (OnChanged != null) + { + OnChanged.Invoke(null); } } // - public void Assign(JToken newValue) { - lock ((object)this) { - switch (newValue.Type) { + public void Assign(JToken newValue) + { + lock ((object)this) + { + switch (newValue.Type) + { case JTokenType.Array: - TomeArray newTomeArray = new TomeArray((JArray)newValue, root); - this.Replace(newTomeArray); + var newTomeArray = new TomeArray((JArray)newValue, root); + Replace(newTomeArray); - if (this.Parent == null) { - // If replace was successfuly move over event handlers and call new onChanged handler + if (Parent == null) + { + // If replace was successfuly move over event handlers and call new OnChanged handler // The instance in which replace would not be successful, is when the old and new values are the same - onChanged -= EmitToParents; - onChanged += newTomeArray.onChanged; - newTomeArray.onChanged = onChanged; - newTomeArray.onDestroy = onDestroy; - onAdd -= EmitChanged; - onAdd += newTomeArray.onAdd; - newTomeArray.onAdd = onAdd; - onDel -= EmitChanged; - onDel += newTomeArray.onDel; - newTomeArray.onDel = onDel; - - if (newTomeArray.onChanged != null) { - newTomeArray.onChanged.Invoke(null); + OnChanged -= EmitToParents; + OnChanged += newTomeArray.OnChanged; + newTomeArray.OnChanged = OnChanged; + newTomeArray.OnDestroy = OnDestroy; + OnAdd -= EmitChanged; + OnAdd += newTomeArray.OnAdd; + newTomeArray.OnAdd = OnAdd; + OnDel -= EmitChanged; + OnDel += newTomeArray.OnDel; + newTomeArray.OnDel = OnDel; + + if (newTomeArray.OnChanged != null) + { + newTomeArray.OnChanged.Invoke(null); } - } else { - // Otherwise call original onChanged handler - if (onChanged != null) { - onChanged.Invoke(null); + } + else + { + // Otherwise call original OnChanged handler + if (OnChanged != null) + { + OnChanged.Invoke(null); } } break; case JTokenType.Object: - TomeObject newTomeObject = new TomeObject((JObject)newValue, root); - this.Replace(newTomeObject); + var newTomeObject = new TomeObject((JObject)newValue, root); + Replace(newTomeObject); - if (this.Parent == null) { - // If replace was successfuly move over event handlers and call new onChanged handler + if (Parent == null) + { + // If replace was successfuly move over event handlers and call new OnChanged handler // The instance in which replace would not be successful, is when the old and new values are the same - onChanged -= EmitToParents; - onChanged += newTomeObject.onChanged; - newTomeObject.onChanged = onChanged; - newTomeObject.onDestroy = onDestroy; - onAdd -= EmitChanged; - onAdd += newTomeObject.onAdd; - newTomeObject.onAdd = onAdd; - onDel -= EmitChanged; - onDel += newTomeObject.onDel; - newTomeObject.onDel = onDel; - - if (newTomeObject.onChanged != null) { - newTomeObject.onChanged.Invoke(null); + OnChanged -= EmitToParents; + OnChanged += newTomeObject.OnChanged; + newTomeObject.OnChanged = OnChanged; + newTomeObject.OnDestroy = OnDestroy; + OnAdd -= EmitChanged; + OnAdd += newTomeObject.OnAdd; + newTomeObject.OnAdd = OnAdd; + OnDel -= EmitChanged; + OnDel += newTomeObject.OnDel; + newTomeObject.OnDel = OnDel; + + if (newTomeObject.OnChanged != null) + { + newTomeObject.OnChanged.Invoke(null); } - } else { - // Otherwise call original onChanged handler - if (onChanged != null) { - onChanged.Invoke(null); + } + else + { + // Otherwise call original OnChanged handler + if (OnChanged != null) + { + OnChanged.Invoke(null); } } break; default: - TomeValue newTomeValue = new TomeValue((JValue)newValue, root); - this.Replace(newTomeValue); + var newTomeValue = new TomeValue((JValue)newValue, root); + Replace(newTomeValue); - if (this.Parent == null) { - // If replace was successfuly move over event handlers and call new onChanged handler + if (Parent == null) + { + // If replace was successfuly move over event handlers and call new OnChanged handler // The instance in which replace would not be successful, is when the old and new values are the same - onChanged -= EmitToParents; - onChanged += newTomeValue.onChanged; - newTomeValue.onChanged = onChanged; - newTomeValue.onDestroy = onDestroy; - - if (newTomeValue.onChanged != null) { - newTomeValue.onChanged.Invoke(null); + OnChanged -= EmitToParents; + OnChanged += newTomeValue.OnChanged; + newTomeValue.OnChanged = OnChanged; + newTomeValue.OnDestroy = OnDestroy; + + if (newTomeValue.OnChanged != null) + { + newTomeValue.OnChanged.Invoke(null); } - } else { - // Otherwise call original onChanged handler - if (onChanged != null) { - onChanged.Invoke(null); + } + else + { + // Otherwise call original OnChanged handler + if (OnChanged != null) + { + OnChanged.Invoke(null); } } break; @@ -138,89 +165,117 @@ public void Assign(JToken newValue) { } // - public void Destroy() { - lock ((object)this) { - foreach (var property in this) { + public void Destroy() + { + lock ((object)this) + { + foreach (KeyValuePair property in this) + { Tome.Destroy(property.Value); } - if (onDestroy != null) { - onDestroy.Invoke(); + if (OnDestroy != null) + { + OnDestroy.Invoke(); } - onChanged = null; - onDestroy = null; - onAdd = null; - onDel = null; + OnChanged = null; + OnDestroy = null; + OnAdd = null; + OnDel = null; } } // - public void Set(string propertyName, JToken value) { - lock ((object)this) { + public void Set(string propertyName, JToken value) + { + lock ((object)this) + { // Make sure the property exists - if (this[propertyName] == null) { - this.Add(propertyName, Tome.Conjure(value, root)); - if (onAdd != null) { - onAdd.Invoke(propertyName); + if (this[propertyName] == null) + { + Add(propertyName, Tome.Conjure(value, root)); + if (OnAdd != null) + { + OnAdd.Invoke(propertyName); } return; } // Assign the property JToken property = this[propertyName]; - switch (property.Type) { + switch (property.Type) + { case JTokenType.Array: - (property as TomeArray).Assign(value); + ((TomeArray)property).Assign(value); break; case JTokenType.Object: - (property as TomeObject).Assign(value); + ((TomeObject)property).Assign(value); break; default: - if ((property as TomeValue) == null) { - Mage.Instance.logger("Tomes").data(property).error("property is not a tome value: " + propertyName.ToString()); + var tomeValue = property as TomeValue; + if (tomeValue == null) + { + Mage.Instance.Logger("Tomes").Data(property).Error("property is not a tome value: " + propertyName); UnityEngine.Debug.Log(this); } - (property as TomeValue).Assign(value); + else + { + tomeValue.Assign(value); + } break; } } } // - public void Del(string propertyName) { - lock ((object)this) { + public void Del(string propertyName) + { + lock ((object)this) + { JToken property = this[propertyName]; - switch (property.Type) { + switch (property.Type) + { case JTokenType.Array: - (property as TomeArray).Destroy(); + ((TomeArray)property).Destroy(); break; case JTokenType.Object: - (property as TomeObject).Destroy(); + ((TomeObject)property).Destroy(); break; default: - if ((property as TomeValue) == null) { - Mage.Instance.logger("Tomes").data(property).error("property is not a tome value: " + propertyName.ToString()); + var tomeValue = property as TomeValue; + if (tomeValue == null) + { + Mage.Instance.Logger("Tomes").Data(property).Error("property is not a tome value: " + propertyName); UnityEngine.Debug.Log(this); } - (property as TomeValue).Destroy(); + else + { + tomeValue.Destroy(); + } break; } - this.Remove(propertyName); - if (onDel != null) { - onDel.Invoke(propertyName); + Remove(propertyName); + if (OnDel != null) + { + OnDel.Invoke(propertyName); } } } // - public void Move(string fromKey, JToken toParent, JToken toKey) { - lock ((object)this) { - if (toParent.Type == JTokenType.Array) { - (toParent as TomeArray).Set((int)toKey, this[fromKey]); - } else { - (toParent as TomeObject).Set((string)toKey, this[fromKey]); + public void Move(string fromKey, JToken toParent, JToken toKey) + { + lock ((object)this) + { + if (toParent.Type == JTokenType.Array) + { + ((TomeArray)toParent).Set((int)toKey, this[fromKey]); + } + else + { + ((TomeObject)toParent).Set((string)toKey, this[fromKey]); } Del(fromKey); @@ -228,8 +283,10 @@ public void Move(string fromKey, JToken toParent, JToken toKey) { } // - public void Rename(string wasKey, string isKey) { - lock ((object)this) { + public void Rename(string wasKey, string isKey) + { + lock ((object)this) + { JToken wasValue = this[wasKey]; Del(wasKey); Set(isKey, wasValue); @@ -237,29 +294,38 @@ public void Rename(string wasKey, string isKey) { } // - public void Swap(string firstKey, JToken secondParent, JToken secondKey) { - lock ((object)this) { + public void Swap(string firstKey, JToken secondParent, JToken secondKey) + { + lock ((object)this) + { JToken secondValue; - if (secondParent.Type == JTokenType.Array) { + if (secondParent.Type == JTokenType.Array) + { secondValue = secondParent[(int)secondKey]; secondParent[(int)secondKey].Replace(this[firstKey]); - } else { + } + else + { secondValue = secondParent[(string)secondKey]; secondParent[(string)secondKey].Replace(this[firstKey]); } this[firstKey].Replace(secondValue); - if (onChanged != null) { - onChanged.Invoke(null); + if (OnChanged != null) + { + OnChanged.Invoke(null); } } } // - public void ApplyOperation(string op, JToken val, JToken root) { - lock ((object)this) { - switch (op) { + public void ApplyOperation(string op, JToken val, JToken root) + { + lock ((object)this) + { + switch (op) + { case "assign": Assign(val); break; @@ -273,22 +339,23 @@ public void ApplyOperation(string op, JToken val, JToken root) { break; case "move": - string fromKey = (string)val["key"]; + var fromKey = (string)val["key"]; JToken toParent = Tome.PathValue(root, val["newParent"] as JArray); JToken toKey = (val["newKey"] != null) ? val["newKey"] : new JValue(fromKey); Move(fromKey, toParent, toKey); break; case "rename": - foreach (var property in val as JObject) { + foreach (KeyValuePair property in (JObject)val) + { string wasKey = property.Key; - string isKey = (string)property.Value; + var isKey = (string)property.Value; Rename(wasKey, isKey); } break; case "swap": - string firstKey = (string)val["key"]; + var firstKey = (string)val["key"]; JToken secondParent = Tome.PathValue(root, val["newParent"] as JArray); JToken secondKey = (val["newKey"] != null) ? val["newKey"] : new JValue(firstKey); Swap(firstKey, secondParent, secondKey); diff --git a/Tomes/TomeValue.cs b/Tomes/TomeValue.cs index 92c7fdb..89be577 100644 --- a/Tomes/TomeValue.cs +++ b/Tomes/TomeValue.cs @@ -2,104 +2,125 @@ using Newtonsoft.Json.Linq; - -namespace Wizcorp.MageSDK.Tomes { - public class TomeValue : JValue { +namespace Wizcorp.MageSDK.Tomes +{ + public class TomeValue : JValue + { // - public Tome.OnChanged onChanged; - public Tome.OnDestroy onDestroy; + public Tome.OnChanged OnChanged; + public Tome.OnDestroy OnDestroy; // private JToken root; - // - public TomeValue(JValue value, JToken _root) : base(value) { + public TomeValue(JValue value, JToken root) : base(value) + { // - root = _root; - if (root == null) { - root = this; + this.root = root; + if (this.root == null) + { + this.root = this; } // - onChanged += EmitToParents; + OnChanged += EmitToParents; } // - private void EmitToParents(JToken oldValue) { - if (this != root) { + private void EmitToParents(JToken oldValue) + { + if (!Equals(this, root)) + { Tome.EmitParentChange(Parent); } } - // - public void Assign(JToken newValue) { - lock ((object)this) { - switch (newValue.Type) { + public void Assign(JToken newValue) + { + lock ((object)this) + { + switch (newValue.Type) + { case JTokenType.Array: - TomeArray newTomeArray = new TomeArray((JArray)newValue, root); - this.Replace(newTomeArray); + var newTomeArray = new TomeArray((JArray)newValue, root); + Replace(newTomeArray); - if (this.Parent == null) { - // If replace was successfuly move over event handlers and call new onChanged handler + if (Parent == null) + { + // If replace was successfuly move over event handlers and call new OnChanged handler // The instance in which replace would not be successful, is when the old and new values are the same - onChanged -= EmitToParents; - onChanged += newTomeArray.onChanged; - newTomeArray.onChanged = onChanged; - newTomeArray.onDestroy = onDestroy; - - if (newTomeArray.onChanged != null) { - newTomeArray.onChanged.Invoke(null); + OnChanged -= EmitToParents; + OnChanged += newTomeArray.OnChanged; + newTomeArray.OnChanged = OnChanged; + newTomeArray.OnDestroy = OnDestroy; + + if (newTomeArray.OnChanged != null) + { + newTomeArray.OnChanged.Invoke(null); } - } else { - // Otherwise call original onChanged handler - if (onChanged != null) { - onChanged.Invoke(null); + } + else + { + // Otherwise call original OnChanged handler + if (OnChanged != null) + { + OnChanged.Invoke(null); } } break; case JTokenType.Object: - TomeObject newTomeObject = new TomeObject((JObject)newValue, root); - this.Replace(newTomeObject); + var newTomeObject = new TomeObject((JObject)newValue, root); + Replace(newTomeObject); - if (this.Parent == null) { - // If replace was successfuly move over event handlers and call new onChanged handler + if (Parent == null) + { + // If replace was successfuly move over event handlers and call new OnChanged handler // The instance in which replace would not be successful, is when the old and new values are the same - onChanged -= EmitToParents; - onChanged += newTomeObject.onChanged; - newTomeObject.onChanged = onChanged; - newTomeObject.onDestroy = onDestroy; - - if (newTomeObject.onChanged != null) { - newTomeObject.onChanged.Invoke(null); + OnChanged -= EmitToParents; + OnChanged += newTomeObject.OnChanged; + newTomeObject.OnChanged = OnChanged; + newTomeObject.OnDestroy = OnDestroy; + + if (newTomeObject.OnChanged != null) + { + newTomeObject.OnChanged.Invoke(null); } - } else { - // Otherwise call original onChanged handler - if (onChanged != null) { - onChanged.Invoke(null); + } + else + { + // Otherwise call original OnChanged handler + if (OnChanged != null) + { + OnChanged.Invoke(null); } } break; default: - TomeValue newTomeValue = new TomeValue((JValue)newValue, root); - this.Replace(newTomeValue); + var newTomeValue = new TomeValue((JValue)newValue, root); + Replace(newTomeValue); - if (this.Parent == null) { - // If replace was successfuly move over event handlers and call new onChanged handler + if (Parent == null) + { + // If replace was successfuly move over event handlers and call new OnChanged handler // The instance in which replace would not be successful, is when the old and new values are the same - onChanged -= EmitToParents; - onChanged += newTomeValue.onChanged; - newTomeValue.onChanged = onChanged; - newTomeValue.onDestroy = onDestroy; - - if (newTomeValue.onChanged != null) { - newTomeValue.onChanged.Invoke(null); + OnChanged -= EmitToParents; + OnChanged += newTomeValue.OnChanged; + newTomeValue.OnChanged = OnChanged; + newTomeValue.OnDestroy = OnDestroy; + + if (newTomeValue.OnChanged != null) + { + newTomeValue.OnChanged.Invoke(null); } - } else { - // Otherwise call original onChanged handler - if (onChanged != null) { - onChanged.Invoke(null); + } + else + { + // Otherwise call original OnChanged handler + if (OnChanged != null) + { + OnChanged.Invoke(null); } } break; @@ -108,22 +129,27 @@ public void Assign(JToken newValue) { } // - public void Destroy() { - lock ((object)this) { - if (onDestroy != null) { - onDestroy.Invoke(); + public void Destroy() + { + lock ((object)this) + { + if (OnDestroy != null) + { + OnDestroy.Invoke(); } - onChanged = null; - onDestroy = null; + OnChanged = null; + OnDestroy = null; } } - // - public void ApplyOperation(string op, JToken val) { - lock ((object)this) { - switch (op) { + public void ApplyOperation(string op, JToken val) + { + lock ((object)this) + { + switch (op) + { case "assign": Assign(val); break; diff --git a/Unity/EditorPlayModeState.cs b/Unity/EditorPlayModeState.cs new file mode 100644 index 0000000..253f79d --- /dev/null +++ b/Unity/EditorPlayModeState.cs @@ -0,0 +1,9 @@ +namespace Wizcorp.MageSDK.Unity +{ + public enum EditorPlayModeState + { + Stopped, + Playing, + Paused + } +} diff --git a/Unity/UnityApplicationState.cs b/Unity/UnityApplicationState.cs index 3019d15..e6346bb 100644 --- a/Unity/UnityApplicationState.cs +++ b/Unity/UnityApplicationState.cs @@ -1,16 +1,22 @@ -using UnityEngine; +using UnityEngine; using System.Collections; using Wizcorp.MageSDK.Utils; -public class UnityApplicationState : MonoSingleton { - public delegate void OnAppStateChanged(bool pauseStatus); - public OnAppStateChanged onAppStateChanged; +namespace Wizcorp.MageSDK.Unity +{ + public class UnityApplicationState : MonoSingleton + { + public delegate void AppStateChanged(bool pauseStatus); + public AppStateChanged OnAppStateChanged; - // What should happen when the application is put into the background - void OnApplicationPause(bool pauseStatus) { - if (onAppStateChanged != null) { - onAppStateChanged.Invoke(pauseStatus); + // What should happen when the application is put into the background + void OnApplicationPause(bool pauseStatus) + { + if (OnAppStateChanged != null) + { + OnAppStateChanged.Invoke(pauseStatus); + } } } } diff --git a/Unity/UnityEditorPlayMode.cs b/Unity/UnityEditorPlayMode.cs index 793b7d0..9454929 100644 --- a/Unity/UnityEditorPlayMode.cs +++ b/Unity/UnityEditorPlayMode.cs @@ -2,60 +2,73 @@ using UnityEditor; -namespace Wizcorp.MageSDK.Editor { - public enum EditorPlayModeState { - Stopped, - Playing, - Paused - } - +namespace Wizcorp.MageSDK.Unity +{ [InitializeOnLoad] - public class UnityEditorPlayMode { + public static class UnityEditorPlayMode + { private static EditorPlayModeState currentState = EditorPlayModeState.Stopped; - public delegate void OnEditorModeChanged(EditorPlayModeState newState); - public static OnEditorModeChanged onEditorModeChanged; + public delegate void EditorModeChanged(EditorPlayModeState newState); + public static EditorModeChanged OnEditorModeChanged; - static UnityEditorPlayMode() { + static UnityEditorPlayMode() + { EditorApplication.playmodeStateChanged += OnUnityPlayModeChanged; - if (EditorApplication.isPaused) { + if (EditorApplication.isPaused) + { currentState = EditorPlayModeState.Paused; } } - private static void OnUnityPlayModeChanged() { - EditorPlayModeState newState = EditorPlayModeState.Stopped; - switch (currentState) { + private static void OnUnityPlayModeChanged() + { + var newState = EditorPlayModeState.Stopped; + switch (currentState) + { case EditorPlayModeState.Stopped: - if (EditorApplication.isPlayingOrWillChangePlaymode) { + if (EditorApplication.isPlayingOrWillChangePlaymode) + { newState = EditorPlayModeState.Playing; - } else { + } + else + { newState = EditorPlayModeState.Paused; } break; case EditorPlayModeState.Playing: - if (EditorApplication.isPaused) { + if (EditorApplication.isPaused) + { newState = EditorPlayModeState.Paused; - } else if (EditorApplication.isPlaying) { + } + else if (EditorApplication.isPlaying) + { newState = EditorPlayModeState.Playing; - } else { + } + else + { newState = EditorPlayModeState.Stopped; } break; case EditorPlayModeState.Paused: - if (EditorApplication.isPlayingOrWillChangePlaymode && !EditorApplication.isPaused) { + if (EditorApplication.isPlayingOrWillChangePlaymode && !EditorApplication.isPaused) + { newState = EditorPlayModeState.Playing; - } else if (EditorApplication.isPlayingOrWillChangePlaymode && EditorApplication.isPaused) { + } + else if (EditorApplication.isPlayingOrWillChangePlaymode && EditorApplication.isPaused) + { newState = EditorPlayModeState.Paused; } break; } - if (onEditorModeChanged != null) { - onEditorModeChanged.Invoke(newState); + if (OnEditorModeChanged != null) + { + OnEditorModeChanged.Invoke(newState); } currentState = newState; } } } + #endif