Exemple #1
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());
            }
        }
Exemple #2
0
        internal static PlayerClusterViewModel BuildClusterViewModelForPlayer(ArkClusterContext context, ArkCloudInventory cloudInventory, DemoMode demoMode, bool incCreaturesCloud)
        {
            var vm = new PlayerClusterViewModel();

            if (incCreaturesCloud)
            {
                foreach (var c in cloudInventory.Dinos)
                {
                    var aliases = ArkSpeciesAliases.Instance.GetAliasesByClassName(c.ClassName);
                    var vmc     = new CloudCreatureViewModel
                    {
                        Name      = demoMode?.GetCreatureName(c.Id1, c.Id2, aliases?.FirstOrDefault()) ?? c.Name,
                        ClassName = c.ClassName,
                        Species   = aliases?.FirstOrDefault(),
                        Aliases   = aliases?.Skip(2).ToArray() ?? new string[] { }, //skip primary name and class name
                        Level     = c.Level
                    };
                    vm.Creatures.Add(vmc);
                }
            }

            return(vm);
        }
Exemple #3
0
        protected override void RunCommand(IEnumerable <string> args)
        {
            List <string> argsList = args.ToList();

            if (showCommandHelp(argsList))
            {
                return;
            }

            string clusterDirectory = argsList[0];
            string outputDirectory  = argsList[1];

            ArkDataManager.LoadData(GlobalOptions.Language);

            List <Action> tasks = GlobalOptions.Parallel ? new List <Action>() : null;

            Stopwatch stopwatch = new Stopwatch(GlobalOptions.UseStopWatch);

            foreach (string path in Directory.EnumerateFiles(clusterDirectory))
            {
                Action task = () => {
                    try {
                        ArkCloudInventory cloudInventory = new ArkCloudInventory().ReadBinary <ArkCloudInventory>(path, ReadingOptions.Create());

                        CustomDataContext context = new CustomDataContext {
                            ObjectContainer = cloudInventory
                        };

                        IPropertyContainer arkData = cloudInventory.InventoryData.GetPropertyValue <IPropertyContainer>("MyArkData");

                        CommonFunctions.WriteJson(Path.Combine(outputDirectory, path + ".json"), (generator, writingOptions) => {
                            generator.WriteStartObject();

                            ArkArrayStruct tamedDinosData = arkData.GetPropertyValue <ArkArrayStruct>("ArkTamedDinosData");
                            if (tamedDinosData != null && tamedDinosData.Any())
                            {
                                generator.WriteArrayFieldStart("creatures");
                                foreach (IStruct dinoStruct in tamedDinosData)
                                {
                                    IPropertyContainer dino = (IPropertyContainer)dinoStruct;
                                    ArkContainer container  = null;
                                    if (cloudInventory.InventoryVersion == 1)
                                    {
                                        ArkArrayUInt8 byteData = dino.GetPropertyValue <ArkArrayUInt8>("DinoData");

                                        container = new ArkContainer(byteData);
                                    }
                                    else if (cloudInventory.InventoryVersion == 3)
                                    {
                                        ArkArrayInt8 byteData = dino.GetPropertyValue <ArkArrayInt8>("DinoData");

                                        container = new ArkContainer(byteData);
                                    }

                                    ObjectReference dinoClass = dino.GetPropertyValue <ObjectReference>("DinoClass");
                                    // Skip "BlueprintGeneratedClass " = 24 chars
                                    string dinoClassName = dinoClass.ObjectString.ToString().Substring(24);
                                    generator.WriteStartObject();

                                    generator.WriteField("type",
                                                         ArkDataManager.HasCreatureByPath(dinoClassName) ? ArkDataManager.GetCreatureByPath(dinoClassName).Name : dinoClassName);

                                    // NPE for unknown versions
                                    Creature creature = new Creature(container.Objects[0], container);
                                    generator.WriteObjectFieldStart("data");
                                    creature.writeAllProperties(generator, context, writeAllFields);
                                    generator.WriteEndObject();

                                    generator.WriteEndObject();
                                }

                                generator.WriteEndArray();
                            }

                            ArkArrayStruct arkItems = arkData.GetPropertyValue <ArkArrayStruct>("ArkItems");
                            if (arkItems != null)
                            {
                                List <Item> items = new List <Item>();
                                foreach (IStruct itemStruct in arkItems)
                                {
                                    IPropertyContainer item    = (IPropertyContainer)itemStruct;
                                    IPropertyContainer netItem = item.GetPropertyValue <IPropertyContainer>("ArkTributeItem");

                                    items.Add(new Item(netItem));
                                }

                                if (items.Any())
                                {
                                    generator.WritePropertyName("items");
                                    Inventory.writeInventoryLong(generator, context, items, writeAllFields);
                                }
                            }

                            generator.WriteEndObject();
                        }, writingOptions);
                    } catch (Exception ex) {
                        Console.Error.WriteLine("Found potentially corrupt cluster data: " + path);
                        if (GlobalOptions.Verbose)
                        {
                            Console.Error.WriteLine(ex.Message);
                            Console.Error.WriteLine(ex.StackTrace);
                        }
                    }
                };

                if (tasks != null)
                {
                    tasks.Add(task);
                }
                else
                {
                    task();
                }
            }

            if (tasks != null)
            {
                Parallel.ForEach(tasks, task => task());
            }

            stopwatch.Stop("Loading cluster data and writing info");
            stopwatch.Print();
        }