Пример #1
0
        static void Main(string[] args)
        {
            var savePath = @"C:\save\NoHibernation\TheIsland.ark";
            // var savePath = @"C:\save\WithHibernation\TheIsland.ark";
            var clusterPath = @"C:\save\cluster";
            var domainOnly  = true; //true: optimize loading of the domain model, false: load everything and keep references in memory

            //prepare
            var cd = new ArkClusterData(clusterPath, loadOnlyPropertiesInDomain: domainOnly);
            var gd = new ArkGameData(savePath, cd, 1, loadOnlyPropertiesInDomain: domainOnly);

            var st = Stopwatch.StartNew();

            //extract savegame
            if (gd.Update(CancellationToken.None, null, true)?.Success == true)
            {
                Console.WriteLine($@"Elapsed (gd) {st.ElapsedMilliseconds:N0} ms");
                st = Stopwatch.StartNew();

                //extract cluster data: no cluster data exists for singlePlayer
                ArkClusterDataUpdateResult clusterResult;
                if (System.IO.File.Exists(clusterPath))
                {
                    clusterResult = cd.Update(CancellationToken.None);
                }

                Console.WriteLine($@"Elapsed (cd) {st.ElapsedMilliseconds:N0} ms");
                st = Stopwatch.StartNew();

                //assign the new data to the domain model
                gd.ApplyPreviousUpdate(domainOnly);

                Console.WriteLine($@"Elapsed (gd-apply) {st.ElapsedMilliseconds:N0} ms");

                Console.WriteLine("Save data loaded!");
            }
            else
            {
                Console.WriteLine("Failed to load save data!");
            }

            Console.WriteLine("Press any key...");
            Console.ReadKey();
        }
Пример #2
0
        static void Main(string[] args)
        {
            var savePath    = @"C:\save\TheIsland.ark";
            var clusterPath = @"C:\save\cluster";

            //prepare
            var cd = new ArkClusterData(clusterPath);
            var gd = new ArkGameData(savePath, cd);

            var st = Stopwatch.StartNew();

            //extract savegame
            if (gd.Update(CancellationToken.None, null, true)?.Success == true)
            {
                Console.WriteLine($@"Elapsed (gd) {st.ElapsedMilliseconds:N0} ms");
                st = Stopwatch.StartNew();

                //extract cluster data
                var clusterResult = cd.Update(CancellationToken.None);

                Console.WriteLine($@"Elapsed (cd) {st.ElapsedMilliseconds:N0} ms");
                st = Stopwatch.StartNew();

                //assign the new data to the domain model
                gd.ApplyPreviousUpdate(false);

                Console.WriteLine($@"Elapsed (gd-apply) {st.ElapsedMilliseconds:N0} ms");

                Console.WriteLine("Save data loaded!");
            }
            else
            {
                Console.WriteLine("Failed to load save data!");
            }

            Console.WriteLine("Press any key...");
            Console.ReadKey();
        }
Пример #3
0
        public async Task Cloud([Remainder] string arguments = null)
        {
            var args = CommandHelper.ParseArgs(arguments, new
            {
                ClusterKey = "",
                Backup     = 0L,
                Stash      = 0L,
                Pop        = 0L,
                Delete     = 0L,
                List       = 0L,
                Details    = 0L,
                Restore    = 0L,
                Target1    = "",
                Target2    = "",
                Skip       = 0
            }, x =>
                                               x.For(y => y.ClusterKey, noPrefix: true)
                                               .For(y => y.Target1, noPrefix: true)
                                               .For(y => y.Target2, noPrefix: true));

            var sb           = new StringBuilder();
            var r_allowedExt = new Regex(@"^(?!tmpprofile)([a-z0-9])+$", RegexOptions.Singleline | RegexOptions.IgnoreCase);

            //for details and restore commands, get hashes from target1 and target2
            int?backupHash = null, cloudSaveHash = null;

            if (args.Details > 0 || args.Restore > 0)
            {
                try
                {
                    backupHash = !string.IsNullOrWhiteSpace(args.Target1) ? (int?)Convert.ToInt32(args.Target1, 16) : null;
                }
                catch { /*ignore exceptions*/ }
            }
            if (args.Restore > 0)
            {
                try
                {
                    cloudSaveHash = !string.IsNullOrWhiteSpace(args.Target2) ? (int?)Convert.ToInt32(args.Target2, 16) : null;
                }
                catch { /*ignore exceptions*/ }
            }

            // for stash and pop commands, check that target1 is a valid tag
            if ((args.Stash > 0 || args.Pop > 0) && !r_allowedExt.IsMatch(args.Target1))
            {
                await Context.Channel.SendMessageAsync($"**The supplied tag is not allowed (only a-z, 0-9)!**");

                return;
            }

            // check that the cluster key is valid
            ArkClusterContext clusterContext = args.ClusterKey != null?_contextManager.GetCluster(args.ClusterKey) : null;

            if (clusterContext == null)
            {
                await Context.Channel.SendMessageAsync($"**Cloud commands need to be prefixed with a valid cluster key.**");

                return;
            }

            // check that there are one or more servers in the cluster
            var serverContexts = _contextManager.GetServersInCluster(clusterContext.Config.Key);

            if (!(serverContexts?.Length > 0))
            {
                await Context.Channel.SendMessageAsync($"**There are no servers in the cluster.**");

                return;
            }

            /* ---------------------------------------------------------------
            *  List cloud save backups available for a given player.
            *  --------------------------------------------------------------- */
            if (args.List > 0)
            {
                var result = GetBackupFiles(clusterContext.Config, serverContexts.Select(x => x.Config.Key).ToArray(), args.List);

                if (result.Count > 0)
                {
                    var tbl = OutputCloudBackupListingTable(result, args.Skip);
                    sb.Append(tbl);
                }
                else
                {
                    sb.AppendLine("**Could not find any cloud save backups...**");
                }
            }

            /* ---------------------------------------------------------------
            *  Stash the current cloud save with a given tag to fetch at a later time.
            *  --------------------------------------------------------------- */
            else if (args.Stash > 0)
            {
                var result = _savegameBackupService.StashCloudSave(clusterContext.Config, args.Stash, args.Target1);
                if (result == StashResult.Successfull)
                {
                    sb.AppendLine($"**Cloud save stashed as '{args.Target1}'!**");
                }
                else if (result == StashResult.SourceMissing)
                {
                    sb.AppendLine("**There is no cloud save to stash...**");
                }
                else if (result == StashResult.TargetExists)
                {
                    sb.AppendLine("**The supplied tag is already being used...**");
                }
                else
                {
                    sb.AppendLine("**Failed to stash cloud save...**");
                }
            }

            /* ---------------------------------------------------------------
            *  Fetch a cloud save previously stashed with a given tag and set it as the current cloud save.
            *  --------------------------------------------------------------- */
            else if (args.Pop > 0)
            {
                var result = _savegameBackupService.PopCloudSave(clusterContext.Config, args.Pop, args.Target1);
                if (result == StashResult.Successfull)
                {
                    sb.AppendLine($"**Cloud save popped from '{args.Target1}'!**");
                }
                else if (result == StashResult.SourceMissing)
                {
                    sb.AppendLine("**The supplied tag does not exist...**");
                }
                else if (result == StashResult.TargetExists)
                {
                    sb.AppendLine("**A cloud save already exists, please delete/stash it before popping...**");
                }
                else
                {
                    sb.AppendLine("**Failed to pop cloud save...**");
                }
            }

            /* ---------------------------------------------------------------
            *  Delete the current cloud save for a given player.
            *  --------------------------------------------------------------- */
            else if (args.Delete > 0)
            {
                var targetPath = Path.Combine(clusterContext.Config.SavePath, $"{args.Delete}");
                if (File.Exists(targetPath))
                {
                    try
                    {
                        File.Delete(targetPath);
                        sb.AppendLine($"**Cloud save deleted!**");
                    }
                    catch
                    {
                        sb.AppendLine($"**Failed to delete cloud save...**");
                    }
                }
                else
                {
                    sb.AppendLine($"**There is no cloud save to delete...**");
                }
            }

            /* ---------------------------------------------------------------
            *  Create a backup of all cloud save files for a given player (including stashed, .tmpprofile etc.)
            *  --------------------------------------------------------------- */
            else if (args.Backup > 0)
            {
                var result = _savegameBackupService.CreateClusterBackupForSteamId(clusterContext.Config, args.Backup);
                if (result != null && result.ArchivePaths?.Length > 0)
                {
                    sb.AppendLine($"**Cloud save backup successfull!**");
                }
                else
                {
                    sb.AppendLine("**Failed to backup cloud save...**");
                }
            }

            /* ---------------------------------------------------------------
            *  Get detailed information for a single backup archive or cloud save file.
            *  --------------------------------------------------------------- */
            else if (args.Details > 0 && backupHash.HasValue)
            {
                var result = GetBackupFiles(clusterContext.Config, serverContexts.Select(x => x.Config.Key).ToArray(), args.Details, backupHash.Value)
                             .Find(x => x.Path.GetHashCode() == backupHash.Value);

                if (result == null)
                {
                    await Context.Channel.SendMessageAsync($"**Failed to find the given backup hash!**");

                    return;
                }

                var data = result.Files.Select(file =>
                {
                    string tmpFilePath = null;
                    ArkCloudInventory cloudInventory = null;
                    try
                    {
                        string filePath = null;
                        if (result is FromServerBackupListEntity)
                        {
                            filePath = result.FullPath;
                        }
                        else
                        {
                            filePath = tmpFilePath = FileHelper.ExtractFileInZipFile(result.FullPath, file);
                        }

                        var cresult    = ArkClusterData.LoadSingle(filePath, CancellationToken.None, true, true);
                        cloudInventory = cresult.Success ? cresult.Data : null;
                    }
                    catch
                    {
                        /*ignore exception*/
                    }
                    finally
                    {
                        if (tmpFilePath != null)
                        {
                            File.Delete(tmpFilePath);
                        }
                    }

                    return(new
                    {
                        FilePath = file,
                        CloudSaveHash = file.GetHashCode(),
                        DinoCount = cloudInventory?.Dinos?.Length,
                        CharactersCount = cloudInventory?.Characters?.Length,
                        ItemsCount = cloudInventory?.Items?.Length
                    });
                }).ToArray();

                var tableBackupFiles = FixedWidthTableHelper.ToString(data, x => x
                                                                      .For(y => y.FilePath, header: "Cloud Save")
                                                                      .For(y => y.CloudSaveHash, header: "Cloud Save Hash", alignment: 1, format: "X")
                                                                      .For(y => y.DinoCount, header: "Dinos", alignment: 1)
                                                                      .For(y => y.CharactersCount, header: "Characters", alignment: 1)
                                                                      .For(y => y.ItemsCount, header: "Items", alignment: 1));

                var tableBackupEntries = OutputCloudBackupListingTable(new[] { result }, 0, 1);

                sb.Append(tableBackupEntries);
                sb.Append($"```{tableBackupFiles}```");
            }

            /* ---------------------------------------------------------------
            *  Restore a single cloud save file from a backup archive or cloud save file (some overlap with the less verbose pop command).
            *  --------------------------------------------------------------- */
            else if (args.Restore > 0 && backupHash.HasValue && cloudSaveHash.HasValue)
            {
                var result = GetBackupFiles(clusterContext.Config, serverContexts.Select(x => x.Config.Key).ToArray(), args.Restore, backupHash.Value)
                             .Find(x => x.Path.GetHashCode() == backupHash.Value);

                if (result == null)
                {
                    await Context.Channel.SendMessageAsync($"**Failed to find the given backup hash!**");

                    return;
                }

                var cloudSaveFile = result.Files.FirstOrDefault(x => x.GetHashCode() == cloudSaveHash.Value);
                if (cloudSaveFile == null)
                {
                    await Context.Channel.SendMessageAsync($"**Failed to find the given cloud save hash!**");

                    return;
                }

                var targetPath = Path.Combine(clusterContext.Config.SavePath, $"{args.Restore}");
                if (File.Exists(targetPath))
                {
                    await Context.Channel.SendMessageAsync("**A cloud save already exists, please delete/stash it before restoring...**");

                    return;
                }

                string tmpFilePath = null;
                try
                {
                    string filePath = null;
                    if (result is FromServerBackupListEntity)
                    {
                        filePath = result.FullPath;
                    }
                    else
                    {
                        filePath = tmpFilePath = FileHelper.ExtractFileInZipFile(result.FullPath, cloudSaveFile);
                    }

                    File.Copy(filePath, targetPath);

                    sb.AppendLine($"**Cloud save successfully restored!**");
                }
                catch
                {
                    /*ignore exception*/
                    sb.AppendLine($"**Failed to restore cloud save...**");
                }
                finally
                {
                    if (tmpFilePath != null)
                    {
                        File.Delete(tmpFilePath);
                    }
                }
            }
            else
            {
                var syntaxHelp = MethodBase.GetCurrentMethod().GetCustomAttribute <SyntaxHelpAttribute>()?.SyntaxHelp;
                var name       = MethodBase.GetCurrentMethod().GetCustomAttribute <CommandAttribute>()?.Text;

                await Context.Channel.SendMessageAsync(string.Join(Environment.NewLine, new string[] {
                    $"**My logic circuits cannot process this command! I am just a bot after all... :(**",
                    !string.IsNullOrWhiteSpace(syntaxHelp) ? $"Help me by following this syntax: **!{name}** {syntaxHelp}" : null
                }.Where(x => x != null)));

                return;
            }

            var msg = sb.ToString();

            if (!string.IsNullOrWhiteSpace(msg))
            {
                await CommandHelper.SendPartitioned(Context.Channel, sb.ToString());
            }
        }
Пример #4
0
        private void SendAnnouncement()
        {
            if (string.IsNullOrWhiteSpace(ClusterFolder) || string.IsNullOrWhiteSpace(SaveFilePath))
            {
                MessageBox.Show("You must select both a cluster folder and a save file path.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            if (string.IsNullOrWhiteSpace(txtWebhookID.Text) || string.IsNullOrWhiteSpace(txtWebhookToken.Text) || !IsInt(txtWebhookID.Text))
            {
                MessageBox.Show("Invalid Webhook data. ID must be an integer and both fields must have an entry.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            client = new Discord.Webhook.DiscordWebhookClient(Convert.ToUInt64(txtWebhookID.Text), txtWebhookToken.Text);

            var cd = new ArkClusterData(ClusterFolder, loadOnlyPropertiesInDomain: true);
            var gd = new ArkGameData(SaveFilePath, cd, loadOnlyPropertiesInDomain: true);

            //extract savegame
            var upd = gd.Update(CancellationToken.None, deferApplyNewData: true);

            if (upd == null)
            {
                return;
            }
            if (upd.Success == true)
            {
                //extract cluster data
                var cr = cd.Update(CancellationToken.None);

                //assign the new data to the domain model
                gd.ApplyPreviousUpdate();

                // Populate Wild dinos
                var wildDinos = gd.WildCreatures;

                // init message
                var message = @"```autohotkey" + Environment.NewLine;

                // Go through entries
                foreach (DataGridViewRow row in dgvTrackList.Rows)
                {
                    if (string.IsNullOrWhiteSpace(row.Cells[0].Value.ToString()) || string.IsNullOrWhiteSpace(row.Cells[1].Value.ToString()))
                    {
                        MessageBox.Show("Incomplete Data", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        return;
                    }

                    var dType        = row.Cells[0].Value.ToString();
                    var searchString = row.Cells[1].Value.ToString();

                    //init controllers
                    var foundDinos = false;

                    // Get desired Dinos
                    var queriedDinos = new List <ArkWildCreature>();
                    queriedDinos = wildDinos.Where(q => q.ClassName.Contains(searchString)).ToList();

                    // Discord
                    if (queriedDinos.Count > 0)
                    {
                        foundDinos = true;
                        message   += $"{dType} sightings on " + queriedDinos.First().Location.MapName + ":" + Environment.NewLine;

                        message += $"_{"_______",-7}_{"________________",-16}_{"_______",-7}_{"_________",-9}_" + Environment.NewLine;
                        message += $"|{"Gender",-7}|{"Type",-16}|{"Level",-7}|{"Location",-9}|" + Environment.NewLine;
                        message += $"|{"_______",-7}|{"________________",-16}|{"_______",-7}|{"_________",-9}|" + Environment.NewLine;
                        foreach (var dino in queriedDinos)
                        {
                            var gender = $" {dino.Gender.ToString()}";
                            var name   = $" {dino.ClassName.Split('_').First()}";
                            var level  = $" {dino.BaseLevel.ToString()}";
                            var loc    = $" {dino.Location.Latitude.Value.ToString("N0", CultureInfo.InvariantCulture)}, { dino.Location.Latitude.Value.ToString("N0", CultureInfo.InvariantCulture)}";
                            message += $"|{gender,-7}|{name,-16}|{level,-7}|{loc,-9}|" + Environment.NewLine;
                        }
                        message += $"|{"_______",-7}|{"________________",-16}|{"_______",-7}|{"_________",-9}|" + Environment.NewLine;
                    }

                    if (MessageTooLong)
                    {
                        message += Environment.NewLine + "```";
                        client.SendMessageAsync(message).Wait();
                        MessageFragsSent = true;
                        message          = @"```autohotkey" + Environment.NewLine;
                    }

                    if (!MessageTooLong && foundDinos && row.Index < dgvTrackList.RowCount)
                    {
                        message += Environment.NewLine + Environment.NewLine + Environment.NewLine;
                    }
                }

                MessageTooLong = message.Length >= 2000 && !MessageFragsSent;

                if (MessageTooLong)
                {
                    SendAnnouncement();
                    MessageTooLong = false;
                }
                else if (!MessageTooLong && !MessageFragsSent)
                {
                    message += Environment.NewLine + "```";
                    client.SendMessageAsync(message).Wait();
                }

                MessageTooLong   = false;
                MessageFragsSent = false;
            }
        }