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(); }
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(); }
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()); } }
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; } }