コード例 #1
0
        private static async void DoCommand(string commandDescription, Func <Task <string> > request, Action <JSONNode> handleSuccess, Action <string> onError)
        {
            OnCommandStart?.Invoke();
            TryLogVerbose(commandDescription);
            if (CheckConnectionKey(commandDescription, onError))
            {
                OnCommandEnd?.Invoke();
                return;
            }

            var response = await request();

            var responseJson = JSONNode.Parse(response);

            TryLogResponse(commandDescription, responseJson);

            if (ReportErrors(commandDescription, responseJson, onError))
            {
                OnCommandEnd?.Invoke();
                return;
            }

            try {
                handleSuccess(responseJson);
                OnCommandEnd?.Invoke();
            } catch (Exception e) {
                TryLogError(commandDescription, e.Message, onError);
                OnCommandEnd?.Invoke();
            }
        }
コード例 #2
0
        //============================================================================================================//
        //                                                                                                            //
        //                                                  SYNC                                                      //
        //                                                                                                            //
        //============================================================================================================//

        /// <summary>
        /// Runs a series of checks to determine the server time sync offset value
        /// This is important if you want the Handy's movements to stay in-sync with locally-playing video content!
        /// Once this function completes, the value of ServerTimeOffset is automatically updated, and will be applied whenever relevant
        /// Be warned! You only have 120 API calls per hour per device and each trip taken during this function counts as one of them!
        /// </summary>
        /// <param name="trips">How many requests to make. The offset value is the average offset time for each trip. Accuracy improves with more trips, the API recommends 30</param>
        /// <param name="onSuccess">Callback indicating success, contains the newly calculated server time offset</param>
        /// <param name="onError">Callback indicating failure, contains the error message</param>
        public static async void GetServerTime(int trips = 30, Action <long> onSuccess = null, Action <string> onError = null)
        {
            const string commandDescription = "Get Server Time";

            OnCommandStart?.Invoke();
            TryLogVerbose(commandDescription);

            if (CheckConnectionKey(commandDescription, onError))
            {
                OnCommandEnd?.Invoke();
                return;
            }

            var offsetAggregate = 0L;

            for (var i = 0; i < trips; i++)
            {
                var startTime = DateTimeOffset.Now.ToUnixTimeMilliseconds();

                var response = await GetAsync(GetUrl("getServerTime"));

                var responseJson = (JSONObject)JSONNode.Parse(response);
                TryLogResponse(commandDescription, responseJson);

                if (responseJson["error"] != null)
                {
                    TryLogError(commandDescription, responseJson["error"], onError);
                    OnCommandEnd?.Invoke();
                    return;
                }

                var endTime             = DateTimeOffset.Now.ToUnixTimeMilliseconds();
                var rtd                 = endTime - startTime;
                var estimatedServerTime = long.Parse(responseJson["serverTime"]) + rtd / 2;
                var offset              = estimatedServerTime - endTime;
                offsetAggregate += offset;
            }

            offsetAggregate /= trips;
            ServerTimeOffset = offsetAggregate;
            if ((int)LogMode >= (int)HandyLogMode.Verbose)
            {
                Debug.Log($"<color=blue>Calculated server offset as {ServerTimeOffset} milliseconds</color>");
            }

            onSuccess?.Invoke(ServerTimeOffset);
            OnCommandEnd?.Invoke();
        }
コード例 #3
0
        /// <summary>
        /// Converts a list of time/position pairs to a CSV file hosted on Handy's servers, ready to be loaded onto a Handy using PrepareSync
        /// </summary>
        /// <param name="patternData">The data to be converted.
        /// The x coordinate represents the time in milliseconds from the beginning of the file
        /// The y coordinate represents the position as a percentage of the current stroke value that the Handy should be at, at the given time value</param>
        /// <param name="onSuccess">Callback indicating success, contains the URL of the newly created CSV file</param>
        /// <param name="onError">Callback indicating failure, contains the error message</param>
        public static async void PatternToUrl(Vector2Int[] patternData, Action <string> onSuccess = null, Action <string> onError = null)
        {
            const string commandDescription = "Pattern to URL";

            OnCommandStart?.Invoke();
            TryLogVerbose(commandDescription);

            if (patternData == null || patternData.Length == 0)
            {
                TryLogError(commandDescription, "No pattern data provided", onError);
                OnCommandEnd?.Invoke();
                return;
            }

            try {
                var csv = "#{\"type\":\"handy\"}";
                foreach (var item in patternData)
                {
                    csv += $"\n{item.x},{item.y}";
                }

                var bytes = Encoding.ASCII.GetBytes(csv);

                var response = await PostAsync(
                    "https://www.handyfeeling.com/api/sync/upload",
                    $"UnityGenerated_{DateTimeOffset.Now.ToUnixTimeMilliseconds()}.csv",
                    new MemoryStream(bytes)
                    );

                var responseJson = JSONNode.Parse(response);
                TryLogResponse(commandDescription, responseJson);

                var url = responseJson["url"] == null ? "" : (string)responseJson["url"];
                onSuccess?.Invoke(url);
                OnCommandEnd?.Invoke();
            } catch (Exception e) {
                TryLogError(commandDescription, "Unexpected error: " + e.Message, onError);
                OnCommandEnd?.Invoke();
            }
        }
コード例 #4
0
        /// <summary>
        /// Uploads a CSV file to Handy's servers, ready to be loaded onto a Handy using PrepareSync
        /// </summary>
        /// <param name="csv">The CSV to be loaded, as a string. Each line should be in the format [time (ms)],[position (%)]</param>
        /// <param name="fileName">Optional filename, one will be generated if left off</param>
        /// <param name="onSuccess">Callback indicating success, contains the URL of the newly uploaded CSV file</param>
        /// <param name="onError">Callback indicating failure, contains the error message</param>
        public static async void CsvToUrl(string csv, string fileName = "", Action <string> onSuccess = null, Action <string> onError = null)
        {
            const string commandDescription = "CSV to URL";

            OnCommandStart?.Invoke();
            TryLogVerbose(commandDescription);

            if (string.IsNullOrEmpty(csv))
            {
                TryLogError(commandDescription, "No CSV provided", onError);
                OnCommandEnd?.Invoke();
                return;
            }

            try {
                var bytes = Encoding.ASCII.GetBytes(csv);

                var response = await PostAsync(
                    "https://www.handyfeeling.com/api/sync/upload",
                    string.IsNullOrEmpty(fileName)
                    ?$"UnityGenerated_{DateTimeOffset.Now.ToUnixTimeMilliseconds()}.csv"
                    : fileName,
                    new MemoryStream(bytes)
                    );

                var responseJson = JSONNode.Parse(response);
                TryLogResponse(commandDescription, responseJson);

                var url = responseJson["url"] == null ? "" : (string)responseJson["url"];
                onSuccess?.Invoke(url);
                OnCommandEnd?.Invoke();
            } catch (Exception e) {
                TryLogError(commandDescription, "Unexpected error: " + e.Message, onError);
                OnCommandEnd?.Invoke();
            }
        }
コード例 #5
0
        private void HandleCommand(string[] args)
        {
            string[] sendArgs = new string[0];
            if (args.Length > 1)
            {
                sendArgs = new string[args.Length - 1];
                for (int i = 1; i < args.Length; i++)
                {
                    sendArgs[i - 1] = args[i];
                }
            }

            string           name     = args[0].ToLower().Trim();
            CommandEventArgs eargs    = new CommandEventArgs(name, sendArgs);
            bool             canceled = OnPlayerCommand.Call(this, eargs, OnAllPlayersCommand).Canceled;

            if (canceled) // If any event canceled us
            {
                return;
            }
            if (Block.NameToBlock(name) != Block.BlockList.UNKNOWN)
            {
                sendArgs = new string[] { name };
                name     = "mode";
            }
            if (Command.Commands.ContainsKey(name))
            {
                ThreadPool.QueueUserWorkItem(delegate {
                    ICommand cmd = Command.Commands[name];
                    if (ServerSettings.GetSettingBoolean("AgreeingToRules"))
                    {
                        if (!Server.AgreedPlayers.Contains(Username) && Group.Permission < 80 && name != "rules" && name != "agree" && name != "disagree")
                        {
                            SendMessage("You need to /agree to the /rules before you can use commands!"); return;
                        }
                    }
                    if (!Group.CanExecute(cmd))
                    {
                        SendMessage(Colors.red + "You cannot use /" + name + "!");
                        return;
                    }
                    try {
                        cmd.Use(this, sendArgs);
                        OnCommandEnd.Call(this, new CommandEndEventArgs(cmd, sendArgs), OnAllCommandEnd);
                    }
                    catch (Exception ex) {
                        Logger.Log("[Error] An error occured when " + Username + " tried to use " + name + "!", System.Drawing.Color.Red, System.Drawing.Color.Black);
                        Logger.LogError(ex);
                    }
                    if (ExtraData.ContainsKey("LastCmd"))
                    {
                        if ((string)(ExtraData["LastCmd"]) != String.Join(" ", args))
                        {
                            ExtraData["LastCmd"] = String.Join(" ", args);
                        }
                    }
                    else
                    {
                        ExtraData.Add("LastCmd", name);
                    }
                });
            }
            else
            {
                SendMessage("Unknown command \"" + name + "\"!");
            }
        }