diff --git a/ARKBreedingStats/ARKBreedingStats.csproj b/ARKBreedingStats/ARKBreedingStats.csproj index da648cf2..b0efff1c 100644 --- a/ARKBreedingStats/ARKBreedingStats.csproj +++ b/ARKBreedingStats/ARKBreedingStats.csproj @@ -99,6 +99,7 @@ + Component @@ -666,6 +667,15 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + TextTemplatingFileGenerator _manifest.json diff --git a/ARKBreedingStats/AsbServer/Connection.cs b/ARKBreedingStats/AsbServer/Connection.cs index cee24de1..40a49a0c 100644 --- a/ARKBreedingStats/AsbServer/Connection.cs +++ b/ARKBreedingStats/AsbServer/Connection.cs @@ -37,7 +37,7 @@ public static async void StartListeningAsync( try { - using (var client = new HttpClient()) + var client = FileService.GetHttpClient; using (var response = await client.GetAsync(requestUri, HttpCompletionOption.ResponseHeadersRead)) { if (!response.IsSuccessStatusCode) @@ -186,16 +186,17 @@ public static async void SendCreatureData(Creature creature, string token) { if (creature == null || string.IsNullOrEmpty(token)) return; - using (var client = new HttpClient()) + var client = FileService.GetHttpClient; + + var contentString = Newtonsoft.Json.JsonConvert.SerializeObject(ImportExportGun.ConvertCreatureToExportGunFile(creature, out _)); + var msg = new HttpRequestMessage(HttpMethod.Put, ApiUri + "export/" + token); + msg.Content = new StringContent(contentString, Encoding.UTF8, "application/json"); + msg.Content.Headers.Add("Content-Length", contentString.Length.ToString()); + using (var response = await client.SendAsync(msg)) { - var contentString = Newtonsoft.Json.JsonConvert.SerializeObject(ImportExportGun.ConvertCreatureToExportGunFile(creature, out _)); - var msg = new HttpRequestMessage(HttpMethod.Put, ApiUri + "export/" + token); - msg.Content = new StringContent(contentString, Encoding.UTF8, "application/json"); - msg.Content.Headers.Add("Content-Length", contentString.Length.ToString()); - var response = await client.SendAsync(msg); Console.WriteLine($"Sent creature data of {creature} using token: {token}\nContent:\n{contentString}"); Console.WriteLine(msg.ToString()); - Console.WriteLine($"Response: Status: {(int)response.StatusCode}, ReasonPhrase: {response.ReasonPhrase}"); + Console.WriteLine($"Response: StatusCode {(int)response.StatusCode}, ReasonPhrase: {response.ReasonPhrase}"); } } diff --git a/ARKBreedingStats/BreedingPlanning/BreedingScore.cs b/ARKBreedingStats/BreedingPlanning/BreedingScore.cs index 31ef4ae1..d5b05bc9 100644 --- a/ARKBreedingStats/BreedingPlanning/BreedingScore.cs +++ b/ARKBreedingStats/BreedingPlanning/BreedingScore.cs @@ -86,8 +86,8 @@ public static List CalculateBreedingScores(Creature[] females, Cre { if (s == Stats.Torpidity || !species.UsesStat(s)) continue; bestPossLevels[s] = 0; - int higherLevel = Math.Max(female.levelsWild[s] + female.levelsMutated?[s] ?? 0, male.levelsWild[s] + male.levelsMutated?[s] ?? 0); - int lowerLevel = Math.Min(female.levelsWild[s] + female.levelsMutated?[s] ?? 0, male.levelsWild[s] + male.levelsMutated?[s] ?? 0); + int higherLevel = Math.Max(female.levelsWild[s] + (female.levelsMutated?[s] ?? 0), male.levelsWild[s] + (male.levelsMutated?[s] ?? 0)); + int lowerLevel = Math.Min(female.levelsWild[s] + (female.levelsMutated?[s] ?? 0), male.levelsWild[s] + (male.levelsMutated?[s] ?? 0)); if (higherLevel < 0) higherLevel = 0; if (lowerLevel < 0) lowerLevel = 0; maxPossibleOffspringLevel += higherLevel; diff --git a/ARKBreedingStats/FileService.cs b/ARKBreedingStats/FileService.cs index ce2c7a83..c46b620b 100644 --- a/ARKBreedingStats/FileService.cs +++ b/ARKBreedingStats/FileService.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Net.Http; using System.Reflection; using System.Runtime.Serialization; @@ -280,5 +281,20 @@ internal static bool IsValidJsonFile(string filePath) //} //catch { return false; } } + + private static HttpClient _httpClient; + + /// + /// Returns a static HttpClient. It's apparently better to reuse on object per app only. + /// + public static HttpClient GetHttpClient + { + get + { + if (_httpClient == null) + _httpClient = new HttpClient(); + return _httpClient; + } + } } } diff --git a/ARKBreedingStats/Form1.cs b/ARKBreedingStats/Form1.cs index f43838b0..7cc99510 100644 --- a/ARKBreedingStats/Form1.cs +++ b/ARKBreedingStats/Form1.cs @@ -273,7 +273,7 @@ private void Form1_Load(object sender, EventArgs e) if (Properties.Settings.Default.LibraryShowMutationLevelColumns) toolStripMenuItemMutationColumns.Checked = true; else - ShowLibraryMutationLevels(false); + ToggleLibraryMutationLevelColumns(false); _creatureListSorter.SortColumnIndex = Properties.Settings.Default.listViewSortCol; _creatureListSorter.Order = Properties.Settings.Default.listViewSortAsc @@ -1282,14 +1282,17 @@ private void Form1_FormClosed(object sender, FormClosedEventArgs e) } // Save column-widths, display-indices and sort-order of the TimerControlListView - SaveListViewSettings(timerList1.ListViewTimers, "TCLVColumnWidths", "TCLVColumnDisplayIndices", "TCLVSortCol", "TCLVSortAsc"); - SaveListViewSettings(pedigree1.ListViewCreatures, "PedigreeListViewColumnWidths"); + SaveListViewSettings(timerList1.ListViewTimers, nameof(Properties.Settings.TCLVColumnWidths), + nameof(Properties.Settings.TCLVColumnDisplayIndices), nameof(Properties.Settings.TCLVSortCol), nameof(Properties.Settings.TCLVSortAsc)); + SaveListViewSettings(pedigree1.ListViewCreatures, nameof(Properties.Settings.PedigreeListViewColumnWidths)); Properties.Settings.Default.PedigreeWidthLeftColum = pedigree1.LeftColumnWidth; - SaveListViewSettings(tribesControl1.ListViewPlayers, "PlayerListColumnWidths", "PlayerListColumnDisplayIndices", "PlayerListSortColumn", "PlayerListSortAsc"); + SaveListViewSettings(tribesControl1.ListViewPlayers, nameof(Properties.Settings.PlayerListColumnWidths), + nameof(Properties.Settings.PlayerListColumnDisplayIndices), nameof(Properties.Settings.PlayerListSortColumn), nameof(Properties.Settings.PlayerListSortAsc)); // Save column-widths, display-indices and sort-order of the listViewLibrary - ShowLibraryMutationLevels(true); // restore collapsed column widths before saving - SaveListViewSettings(listViewLibrary, "columnWidths", "libraryColumnDisplayIndices"); + if (!Properties.Settings.Default.LibraryShowMutationLevelColumns) + ToggleLibraryMutationLevelColumns(true); // restore collapsed column widths before saving + SaveListViewSettings(listViewLibrary, nameof(Properties.Settings.columnWidths), nameof(Properties.Settings.libraryColumnDisplayIndices)); Properties.Settings.Default.listViewSortCol = _creatureListSorter.SortColumnIndex; Properties.Settings.Default.listViewSortAsc = _creatureListSorter.Order == SortOrder.Ascending; @@ -2089,7 +2092,7 @@ private void SetupExportFileWatcher() if (_fileWatcherExports == null) { _fileWatcherExports = - new FileWatcherExports(exportFolderDefault, ImportExportedAddIfPossible_WatcherThread); + new FileWatcherExports(exportFolderDefault, ImportExportedFileChanged, this); } else { diff --git a/ARKBreedingStats/Form1.extractor.cs b/ARKBreedingStats/Form1.extractor.cs index 9751feec..31a17458 100644 --- a/ARKBreedingStats/Form1.extractor.cs +++ b/ARKBreedingStats/Form1.extractor.cs @@ -328,8 +328,9 @@ private bool ExtractLevels(bool autoExtraction = false, bool statInputsHighPreci } // get mean-level (most probable for the wild levels) - // TODO handle species without wild levels in speed better (some flyers) - double meanWildLevel = Math.Round((double)_extractor.LevelWildSum / 7, 1); + var statsWithLevels = Enumerable.Range(0, Stats.StatsCount).Aggregate(0, + (c, s) => c += s != Stats.Torpidity && speciesSelector1.SelectedSpecies.CanLevelUpWildOrHaveMutations(s) ? 1 : 0); + double meanWildLevel = Math.Round((double)_extractor.LevelWildSum / statsWithLevels, 1); bool nonUniqueStats = false; for (int s = 0; s < Stats.StatsCount; s++) diff --git a/ARKBreedingStats/Form1.importExported.cs b/ARKBreedingStats/Form1.importExported.cs index 1c73b371..75fbe8cf 100644 --- a/ARKBreedingStats/Form1.importExported.cs +++ b/ARKBreedingStats/Form1.importExported.cs @@ -166,16 +166,18 @@ private void ExportedCreatureList_CopyValuesToExtractor(importExported.ExportedC } } - private void ImportExportedAddIfPossible_WatcherThread(string filePath, importExported.FileWatcherExports fwe) + /// + /// The fileWatcher detected a new or changed file in the watched folder. + /// + private void ImportExportedFileChanged(string filePath, importExported.FileWatcherExports fwe) { fwe.Watching = false; - // wait a moment until the file is readable. why is this necessary? blocked by fileWatcher? + // wait a moment until the file is fully written System.Threading.Thread.Sleep(200); - // moving to the archived folder can trigger another fileWatcherEvent, first check if the file is still there + // moving a file to the archived folder can trigger another fileWatcherEvent, first check if the file is still there if (File.Exists(filePath)) - // fileWatcher is on another thread, invoke ui-thread to work with ui - Invoke(new Action(delegate { ImportExportedAddIfPossible(filePath); })); + ImportExportedAddIfPossible(filePath); fwe.Watching = true; } diff --git a/ARKBreedingStats/Form1.library.cs b/ARKBreedingStats/Form1.library.cs index fa229742..209d1ffd 100644 --- a/ARKBreedingStats/Form1.library.cs +++ b/ARKBreedingStats/Form1.library.cs @@ -12,6 +12,7 @@ using System.IO; using System.Text; using System.Text.RegularExpressions; +using ARKBreedingStats.importExportGun; using ARKBreedingStats.library; using ARKBreedingStats.settings; @@ -2076,12 +2077,12 @@ private void resetColumnWidthNoMutationLevelColumnsToolStripMenuItem_Click(objec private void restoreMutationLevelsASAToolStripMenuItem_Click(object sender, EventArgs e) { - LibraryColumnsMutationsWidth(false); + ToggleLibraryMutationLevelColumns(true, true); } private void collapseMutationsLevelsASEToolStripMenuItem_Click(object sender, EventArgs e) { - LibraryColumnsMutationsWidth(true); + ToggleLibraryMutationLevelColumns(false); } private void ResetColumnWidthListViewLibrary(bool mutationColumnWidthsZero) @@ -2093,25 +2094,18 @@ private void ResetColumnWidthListViewLibrary(bool mutationColumnWidthsZero) : ci < ColumnIndexFirstStat || ci >= ColumnIndexPostColor ? 60 : ci >= ColumnIndexFirstStat + Stats.StatsCount + Stats.StatsCount ? 30 // color : ci < ColumnIndexFirstStat + Stats.StatsCount ? statWidths[ci - ColumnIndexFirstStat] // wild levels + : ci - ColumnIndexFirstStat - Stats.StatsCount == Stats.Torpidity ? 0 // no mutations for torpidity : (int)(statWidths[ci - ColumnIndexFirstStat - Stats.StatsCount] * 1.24); // mutated needs space for one more letter - if (mutationColumnWidthsZero) - LibraryColumnsMutationsWidth(true); + // save in settings so it can be used when toggle the mutation columns, which use the settings + var widths = new int[listViewLibrary.Columns.Count]; + for (int c = 0; c < widths.Length; c++) + widths[c] = listViewLibrary.Columns[c].Width; + Properties.Settings.Default.columnWidths = widths; - listViewLibrary.EndUpdate(); - } + if (mutationColumnWidthsZero) + ToggleLibraryMutationLevelColumns(false); - /// - /// Set width of mutation level columns to zero or restore. - /// - private void LibraryColumnsMutationsWidth(bool collapse) - { - listViewLibrary.BeginUpdate(); - var statWidths = Stats.UsuallyVisibleStats.Select(w => !collapse && w ? 38 : 0).ToArray(); - for (int c = 0; c < Stats.StatsCount; c++) - { - listViewLibrary.Columns[c + ColumnIndexFirstStat + Stats.StatsCount].Width = statWidths[c]; - } listViewLibrary.EndUpdate(); } @@ -2119,20 +2113,30 @@ private void toolStripMenuItemMutationColumns_CheckedChanged(object sender, Even { var showMutationColumns = toolStripMenuItemMutationColumns.Checked; Properties.Settings.Default.LibraryShowMutationLevelColumns = showMutationColumns; - ShowLibraryMutationLevels(showMutationColumns); + ToggleLibraryMutationLevelColumns(showMutationColumns); } /// /// Set width of library mutation level columns to 0 or restore. /// - private void ShowLibraryMutationLevels(bool show) + private void ToggleLibraryMutationLevelColumns(bool show, bool resetWidth = false) { var widths = Properties.Settings.Default.columnWidths; - if (widths == null || widths.Length < ColumnIndexFirstStat + 2 * Stats.StatsCount) return; - + if (widths == null || widths.Length < ColumnIndexFirstStat + 2 * Stats.StatsCount) + { + SaveListViewSettings(listViewLibrary, nameof(Properties.Settings.columnWidths), nameof(Properties.Settings.libraryColumnDisplayIndices)); + widths = Properties.Settings.Default.columnWidths; + } + listViewLibrary.BeginUpdate(); if (show) { + if (resetWidth) + { + var mutationStatWidths = Stats.UsuallyVisibleStats.Select((v, i) => v && i != Stats.Torpidity ? 37 : 0).ToArray(); + mutationStatWidths.CopyTo(widths, ColumnIndexFirstStat + Stats.StatsCount); + } + for (int ci = ColumnIndexFirstStat + Stats.StatsCount; ci < ColumnIndexFirstStat + 2 * Stats.StatsCount; ci++) listViewLibrary.Columns[ci].Width = widths[ci]; } diff --git a/ARKBreedingStats/NamePatterns/NameList.cs b/ARKBreedingStats/NamePatterns/NameList.cs new file mode 100644 index 00000000..571894d9 --- /dev/null +++ b/ARKBreedingStats/NamePatterns/NameList.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ARKBreedingStats.NamePatterns +{ + /// + /// Loads a list of names from a file. + /// + internal static class NameList + { + /// + /// Contains all name lists, key is the fileName suffix. + /// + private static readonly Dictionary nameLists = new Dictionary(); + private static readonly Dictionary listFileCheckedAt = new Dictionary(); + + /// + /// Returns a name from a list. If the file wasn't checked recently, it's checked and reloaded. + /// + public static string GetName(int nameIndex = 0, string listSuffix = null) + { + if (nameIndex < 0) return null; + var nameList = GetNameList(listSuffix); + if (nameList == null || nameList.Length == 0) return null; + + if (nameIndex >= nameList.Length) + nameIndex %= nameList.Length; + return nameList[nameIndex]; + } + + /// + /// Returns a name list. + /// + public static string[] GetNameList(string listSuffix = null) + { + if (listSuffix == null) listSuffix = string.Empty; + string[] list; + if (!listFileCheckedAt.TryGetValue(listSuffix, out var checkedAt) + || (DateTime.Now - checkedAt).TotalSeconds > 10 + || !nameLists.TryGetValue(listSuffix, out list)) + { + list = LoadList(listSuffix, checkedAt); + } + return list; + } + + private static string[] LoadList(string listSuffix, DateTime checkedAt) + { + var filePath = FileService.GetJsonPath("creatureNames" + listSuffix + ".txt"); + + if (!File.Exists(filePath)) return null; + try + { + if (new FileInfo(filePath).LastWriteTime > checkedAt) + { + var list = File.ReadAllLines(filePath); + nameLists[listSuffix] = list; + } + listFileCheckedAt[listSuffix] = DateTime.Now; + return nameLists[listSuffix]; + } + catch { } + return null; + } + } +} diff --git a/ARKBreedingStats/NamePatterns/NamePattern.cs b/ARKBreedingStats/NamePatterns/NamePattern.cs index f9844ff3..3bc64761 100644 --- a/ARKBreedingStats/NamePatterns/NamePattern.cs +++ b/ARKBreedingStats/NamePatterns/NamePattern.cs @@ -16,6 +16,8 @@ public static class NamePattern /// private const string PipeEscapeSequence = @"\pipe"; + public static Random Random = new Random(); + /// /// Generate a creature name with the naming pattern. /// @@ -203,9 +205,6 @@ public static Dictionary CreateTokenDictionary(Creature creature double imp = creature.imprintingBonus * 100; double eff = creature.tamingEff * 100; - Random rand = new Random(DateTime.Now.Millisecond); - string randStr = rand.Next(0, 999999).ToString("000000"); - string effImp = "Z"; string prefix = string.Empty; if (creature.isBred) @@ -332,7 +331,7 @@ public static Dictionary CreateTokenDictionary(Creature creature { "genn", (speciesCreatures?.Count(c=>c.generation==generation) ?? 0 + 1).ToString()}, { "nr_in_gen", nrInGeneration.ToString()}, { "nr_in_gen_sex", nrInGenerationAndSameSex.ToString()}, - { "rnd", randStr }, + { "rnd", Random.Next(0, 999999).ToString("000000")}, { "ln", libraryCreatureCount.ToString()}, { "tn", speciesCount.ToString()}, { "sn", speciesSexCount.ToString()}, diff --git a/ARKBreedingStats/NamePatterns/NamePatternFunctions.cs b/ARKBreedingStats/NamePatterns/NamePatternFunctions.cs index efa45ff7..4ebff1d5 100644 --- a/ARKBreedingStats/NamePatterns/NamePatternFunctions.cs +++ b/ARKBreedingStats/NamePatterns/NamePatternFunctions.cs @@ -51,6 +51,7 @@ private static string ParametersInvalid(string specificError, string expression, {"float_div", FunctionFloatDiv}, {"div", FunctionDiv}, {"casing", FunctionCasing}, + {"rand", FunctionRand }, {"replace", FunctionReplace}, {"regexreplace", FunctionRegExReplace}, {"customreplace", FunctionCustomReplace}, @@ -58,7 +59,8 @@ private static string ParametersInvalid(string specificError, string expression, {"color", FunctionColor}, {"colornew", FunctionColorNew}, {"indexof", FunctionIndexOf}, - {"md5", FunctionMd5} + {"md5", FunctionMd5}, + {"listname", FunctionListName } }; private static string FunctionIf(Match m, NamePatternParameters p) @@ -247,6 +249,20 @@ private static string FunctionCasing(Match m, NamePatternParameters p) return ParametersInvalid($"casing expects 'U', 'L' or 'T', given is '{m.Groups[3].Value}'", m.Groups[0].Value, p.DisplayError); } + private static string FunctionRand(Match m, NamePatternParameters p) + { + // parameter: 1: to (if one parameter), from (if two parameters), 2: to + // to is exclusive + int.TryParse(m.Groups[2].Value, out var from); + if (!int.TryParse(m.Groups[3].Value, out var to)) + { + to = from; + from = 0; + } + if (from < 0 || from >= to) return string.Empty; + return NamePattern.Random.Next(from, to).ToString(); + } + private static string FunctionReplace(Match m, NamePatternParameters p) { // parameter: 1: replace, 2: text, 3: find, 4: replace @@ -360,6 +376,14 @@ private static string FunctionMd5(Match m, NamePatternParameters p) return sb.ToString(); } + private static string FunctionListName(Match m, NamePatternParameters p) + { + // parameter: 1: name index, 2: list suffix + if (!int.TryParse(m.Groups[2].Value, out var nameIndex)) return string.Empty; + + return NameList.GetName(nameIndex, m.Groups[3].Value); + } + public static void Dispose() { _md5?.Dispose(); diff --git a/ARKBreedingStats/NamePatterns/PatternEditor.cs b/ARKBreedingStats/NamePatterns/PatternEditor.cs index 0e76df89..74cbdbd6 100644 --- a/ARKBreedingStats/NamePatterns/PatternEditor.cs +++ b/ARKBreedingStats/NamePatterns/PatternEditor.cs @@ -527,20 +527,22 @@ private void InsertText(string text) {"expr", "{{#expr: expression }}, simple calculation with two operands and one operator. Possible operators are +, -, *, /.\n{{#expr: {hp} * 2 }}" }, {"len", "{{#len: string }}, returns the length of the passed string.\n{{#len: {isTophp}{isTopdm}{isTopwe} }}" }, {"substring","{{#substring: text | start | length }}. Length can be omitted. If start is negative it takes the characters from the end. If length is negative it takes the characters until that position from the end\n{{#substring: {species} | 0 | 4 }}"}, + {"rand","{{#rand: min | max (exclusive) }} or {{#rand: max (exclusive) }}\n{{#rand: 100 }}"}, {"replace","{{#replace: text | find | replaceBy }}\n{{#replace: {species} | Aberrant | Ab }}"}, {"regexreplace","{{#regexreplace: text | pattern | replaceBy }}\nUse &{ instead {, &&vline; instead | and &} instead of }.\n{{#regexreplace: hp-st-we- | \\-$ | }}"}, {"customreplace","{{#customreplace: text }}. Replaces the text with a value saved in the file customReplacings.json.\nIf a second parameter is given, that is returned if the key is not available.\n{{#customreplace: {species} }}"}, {"float divide by","{{#float_div: number | divisor | formatString }}, can be used to display stat-values in thousands, e.g. '{{#float_div: {hp_vb} | 1000 | F2 }}kHP'.\n{{#float_div: {hp_vb} | 1000 | F2 }}"}, {"divide by","{{#div: number | divisor }}, can be used to display stat-values in thousands, e.g. '{{#div: {hp_vb} | 1000 }}kHP'.\n{{#div: {hp_vb} | 1000 }}"}, - {"padleft","{{#padleft: number | length | padding character }}\n{{#padleft: {hp_vb} | 8 | 0 }}"}, - {"padright","{{#padright: number | length | padding character }}\n{{#padright: {hp_vb} | 8 | _ }}"}, + {"listName","{{#listName: nameIndex | listSuffix }}, takes a name from a list in the file creatureNames[suffix].txt\n{{#listName: 0 | {sex_short} }}"}, + {"padLeft","{{#padLeft: number | length | padding character }}\n{{#padLeft: {hp_vb} | 8 | 0 }}"}, + {"padRight","{{#padRight: number | length | padding character }}\n{{#padRight: {hp_vb} | 8 | _ }}"}, {"casing","{{#casing: text | case (U, L, T) }}. U for UPPER, L for lower, T for Title.\n{{#casing: {species} | U }}"}, {"time","{{#time: formatString }}\n{{#time: yyyy-MM-dd_HH:mm }}"}, {"format","{{#format: number | formatString }}\n{{#format: {hp_vb} | 000000 }}"}, {"format_int","Like #format, but supports \"x\" in the format for hexadecimal representations. {{#format_int: number | formatString }}\n{{#format_int: {{#color: 0 }} | x2 }}"}, {"color","{{#color: regionId | return color name | return value even for unused regions }}. Returns the colorId of the region. If the second parameter is not empty, the color name will be returned. Unused regions will only return a value if the third value is not empty.\n{{#color: 0 | true }}"}, {"colorNew","{{#colorNew: regionId }}. Returns newInRegion if the region contains a color that is not yet available in that species. Returns newInSpecies if that color is not yet available in any region of that species.\n{{#colorNew: 0 }}"}, - {"indexof","{{#indexof: source string | string to find }}. Returns the index of the second parameter in the first parameter. If the string is not contained, an empty string will be returned.\n{{#indexof: hello | ll }}"}, + {"indexOf","{{#indexof: source string | string to find }}. Returns the index of the second parameter in the first parameter. If the string is not contained, an empty string will be returned.\n{{#indexof: hello | ll }}"}, {"md5", "{{#md5: string }}, returns the md5 hash of a given string\n{{#md5: {hp}{st}{we} }}"} }; diff --git a/ARKBreedingStats/Properties/AssemblyInfo.cs b/ARKBreedingStats/Properties/AssemblyInfo.cs index e812401e..eec1282a 100644 --- a/ARKBreedingStats/Properties/AssemblyInfo.cs +++ b/ARKBreedingStats/Properties/AssemblyInfo.cs @@ -30,6 +30,6 @@ // Revision // [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("0.59.4.0")] +[assembly: AssemblyFileVersion("0.59.5.0")] [assembly: NeutralResourcesLanguage("en")] diff --git a/ARKBreedingStats/StatResult.cs b/ARKBreedingStats/StatResult.cs index 84610d5d..53e0643e 100644 --- a/ARKBreedingStats/StatResult.cs +++ b/ARKBreedingStats/StatResult.cs @@ -15,5 +15,7 @@ public StatResult(int levelWild, int levelDom, MinMaxDouble? TE = null) this.levelDom = levelDom; this.TE = TE ?? new MinMaxDouble(-1); } + + public override string ToString() => $"w: {levelWild}, d: {levelDom}, TE: {TE.Mean:.000}"; } } diff --git a/ARKBreedingStats/_manifest.json b/ARKBreedingStats/_manifest.json index 7a72e678..b3cec913 100644 --- a/ARKBreedingStats/_manifest.json +++ b/ARKBreedingStats/_manifest.json @@ -4,7 +4,7 @@ "ARK Smart Breeding": { "Id": "ARK Smart Breeding", "Category": "main", - "version": "0.59.4.0" + "version": "0.59.5.0" }, "SpeciesColorImages": { "Id": "SpeciesColorImages", diff --git a/ARKBreedingStats/importExported/FileWatcherExports.cs b/ARKBreedingStats/importExported/FileWatcherExports.cs index 6b8735cd..f353f016 100644 --- a/ARKBreedingStats/importExported/FileWatcherExports.cs +++ b/ARKBreedingStats/importExported/FileWatcherExports.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Windows.Forms; namespace ARKBreedingStats.importExported { @@ -8,13 +9,14 @@ public class FileWatcherExports : IDisposable private readonly FileSystemWatcher _fileWatcherExport; private readonly Action _callbackNewFile; - public FileWatcherExports(string folderToWatch, Action callbackNewFile) + public FileWatcherExports(string folderToWatch, Action callbackNewFile, Control synchronizingObject) { _callbackNewFile = callbackNewFile; _fileWatcherExport = new FileSystemWatcher { - NotifyFilter = NotifyFilters.LastWrite + NotifyFilter = NotifyFilters.LastWrite, + SynchronizingObject = synchronizingObject }; _fileWatcherExport.Created += OnChanged; _fileWatcherExport.Changed += OnChanged; diff --git a/ARKBreedingStats/importExported/ImportExported.cs b/ARKBreedingStats/importExported/ImportExported.cs index db9dff44..9ec313be 100644 --- a/ARKBreedingStats/importExported/ImportExported.cs +++ b/ARKBreedingStats/importExported/ImportExported.cs @@ -101,7 +101,7 @@ public static CreatureValues ImportExportedCreature(string filePath) break; case "DinoClass": // despite the property is called DinoClass it contains the complete blueprint-path - cv.Species = Values.V.SpeciesByBlueprint(text,true); + cv.Species = Values.V.SpeciesByBlueprint(text, true); if (cv.Species == null) cv.speciesBlueprint = text; // species is unknown, check the needed mods later break; @@ -144,7 +144,10 @@ public static CreatureValues ImportExportedCreature(string filePath) break; case "BabyAge": if (cv.Species?.breeding != null) + { cv.growingUntil = DateTime.Now.AddSeconds((int)(cv.Species.breeding.maturationTimeAdjusted * (1 - value))); + if (value < 1) cv.isBred = true; + } break; case "CharacterLevel": cv.level = (int)value; diff --git a/ARKBreedingStats/json/creatureNamesF.txt b/ARKBreedingStats/json/creatureNamesF.txt new file mode 100644 index 00000000..784baa65 --- /dev/null +++ b/ARKBreedingStats/json/creatureNamesF.txt @@ -0,0 +1,38 @@ +Aurora +Bess +Bones +Breeze +Casey +Casia +Catlin +Chromy +Chuckles +Cosmo +Cupcake +Danele +Daphne +Durva +Electra +Ellie +Elora +Flare +Ginger +Hope +Indigo +Jackie +Layka +Myst +Nectar +Oracle +Pandora +Peachy +Peanuts +Princess +Raye +Sabre +Shellbie +Shine +Tia +Vanity +Wilde +Zara \ No newline at end of file diff --git a/ARKBreedingStats/json/creatureNamesM.txt b/ARKBreedingStats/json/creatureNamesM.txt new file mode 100644 index 00000000..062216f2 --- /dev/null +++ b/ARKBreedingStats/json/creatureNamesM.txt @@ -0,0 +1,19 @@ +Austin +Bran +Cosmo +Dearborn +Eclipse +Fuzz +Gazoo +Hercules +Indy +Jiggles +Lightning +Marble +Noah +Pepper +Rancher +Sparkler +Tweeter +Whiskers +Zion \ No newline at end of file diff --git a/ARKBreedingStats/json/creatureNamesU.txt b/ARKBreedingStats/json/creatureNamesU.txt new file mode 100644 index 00000000..71d013db --- /dev/null +++ b/ARKBreedingStats/json/creatureNamesU.txt @@ -0,0 +1,28 @@ +Acorn +Bailey +Blaze +Casey +Caramel +Dara +Echo +Fluffy +Goldy +Harper +Indie +Java +Kiwi +Lake +Marley +Max +Ninja +Olive +Onyx +Phoenix +Quinn +Riley +Sable +Scout +Smokey +Sunny +Tiny +Waffles \ No newline at end of file diff --git a/ARKBreedingStats/json/values/_manifest.json b/ARKBreedingStats/json/values/_manifest.json index 288ef31d..693318b2 100644 --- a/ARKBreedingStats/json/values/_manifest.json +++ b/ARKBreedingStats/json/values/_manifest.json @@ -6,7 +6,7 @@ "mod": { "id": "1083349027", "tag": "SpeedyFlyers", "title": "Najs Speedy Flyers" } }, "1090809604-Pyria.json": { - "version": "358.17.1700355701", + "version": "358.17.1703902790", "mod": { "id": "1090809604", "tag": "Pyria", "title": "Pyria: Mythos Evolved" } }, "1092784125-Gryphons.json": { @@ -30,7 +30,7 @@ "mod": { "id": "1139775728", "tag": "Confuciusornis", "title": "Confuciusornis" } }, "1169020368-Trex.json": { - "version": "358.17.1701004683", + "version": "358.17.1703269186", "mod": { "id": "1169020368", "tag": "Trex", "title": "Ark Creature Rebalance (AG Reborn)" } }, "1178308359-ShadDragon.json": { diff --git a/ARKBreedingStats/library/CreatureCollection.cs b/ARKBreedingStats/library/CreatureCollection.cs index 424290ac..f7ef4908 100644 --- a/ARKBreedingStats/library/CreatureCollection.cs +++ b/ARKBreedingStats/library/CreatureCollection.cs @@ -80,7 +80,7 @@ public CreatureCollection() /// Indicates the game the library is used for. Possible values are "ASE" (default) for ARK: Survival Evolved or "ASA" for ARK: Survival Ascended. /// [JsonProperty("Game")] - private string _game = "ASE"; + private string _game = Ark.Ase; /// /// Used for the exportGun mod. @@ -150,6 +150,12 @@ public CreatureCollection() private Dictionary _creatureCountBySpecies; private int _totalCreatureCount; + /// + /// ServerMultipliers uri on the server to pull the settings. + /// + [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] + public string ServerSettingsUriSource; + /// /// Calculates a hashcode for a list of mods and their order. Can be used to check for changes. /// diff --git a/ARKBreedingStats/library/DummyCreatures.cs b/ARKBreedingStats/library/DummyCreatures.cs index 22c0cd47..52d7323c 100644 --- a/ARKBreedingStats/library/DummyCreatures.cs +++ b/ARKBreedingStats/library/DummyCreatures.cs @@ -3,6 +3,7 @@ using System.Linq; using ARKBreedingStats.BreedingPlanning; using ARKBreedingStats.Library; +using ARKBreedingStats.NamePatterns; using ARKBreedingStats.species; using ARKBreedingStats.values; @@ -15,6 +16,9 @@ public static class DummyCreatures { public static DummyCreatureCreationSettings LastSettings; + private static string[] _namesFemale; + private static string[] _namesMale; + /// /// Creates a list of random creatures. /// @@ -147,18 +151,29 @@ public static Creature CreateCreature(Species species, double difficulty = 5, bo string name = null; if (doTame) { + if (_namesFemale == null) + _namesFemale = NameList.GetNameList("F"); + if (_namesMale == null) + _namesMale = NameList.GetNameList("M"); var names = sex == Sex.Female ? _namesFemale : _namesMale; - name = names[rand.Next(names.Length)]; - if (nameCounter != null) + if (names == null) { - if (nameCounter.TryGetValue(name, out var nameCount)) - { - nameCounter[name]++; - name += $" {nameCount + 1}"; - } - else + name = "?"; + } + else + { + name = names[rand.Next(names.Length)]; + if (nameCounter != null) { - nameCounter.Add(name, 1); + if (nameCounter.TryGetValue(name, out var nameCount)) + { + nameCounter[name]++; + name += $" {nameCount + 1}"; + } + else + { + nameCounter.Add(name, 1); + } } } } @@ -377,9 +392,6 @@ private static List BreedCreatures(Creature[] creatures, Species speci } - private static readonly string[] _namesFemale = { "Aurora", "Bess", "Bones", "Breeze", "Casey", "Casia", "Catlin", "Chromy", "Chuckles", "Cosmo", "Cupcake", "Danele", "Daphne", "Durva", "Electra", "Ellie", "Elora", "Flare", "Ginger", "Hope", "Indigo", "Jackie", "Layka", "Myst", "Nectar", "Oracle", "Pandora", "Peachy", "Peanuts", "Princess", "Raye", "Sabre", "Shellbie", "Shine", "Tia", "Vanity", "Wilde", "Zara" }; - private static readonly string[] _namesMale = { "Austin", "Bran", "Cosmo", "Dearborn", "Eclipse", "Fuzz", "Gazoo", "Hercules", "Indy", "Jiggles", "Lightning", "Marble", "Noah", "Pepper", "Rancher", "Sparkler", "Tweeter", "Whiskers", "Zion" }; - #region Binomial distributed levels /// diff --git a/ARKBreedingStats/settings/Settings.Designer.cs b/ARKBreedingStats/settings/Settings.Designer.cs index f6b49e4f..6f48f8a7 100644 --- a/ARKBreedingStats/settings/Settings.Designer.cs +++ b/ARKBreedingStats/settings/Settings.Designer.cs @@ -98,6 +98,8 @@ private void InitializeComponent() this.label12 = new System.Windows.Forms.Label(); this.numericUpDownMaxBreedingSug = new ARKBreedingStats.uiControls.Nud(); this.groupBox5 = new System.Windows.Forms.GroupBox(); + this.NudWildDinoCharacterFoodDrainMultiplier = new ARKBreedingStats.uiControls.Nud(); + this.label69 = new System.Windows.Forms.Label(); this.label67 = new System.Windows.Forms.Label(); this.NudWildDinoTorporDrainMultiplier = new ARKBreedingStats.uiControls.Nud(); this.nudDinoCharacterFoodDrainEvent = new ARKBreedingStats.uiControls.Nud(); @@ -349,8 +351,8 @@ private void InitializeComponent() this.label1 = new System.Windows.Forms.Label(); this.panel1 = new System.Windows.Forms.Panel(); this.colorDialog1 = new System.Windows.Forms.ColorDialog(); - this.label69 = new System.Windows.Forms.Label(); - this.NudWildDinoCharacterFoodDrainMultiplier = new ARKBreedingStats.uiControls.Nud(); + this.BtRemoteServerSettingsUri = new System.Windows.Forms.Button(); + this.TbRemoteServerSettingsUri = new System.Windows.Forms.TextBox(); this.groupBoxMultiplier.SuspendLayout(); this.groupBox2.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.nudTamedDinoCharacterFoodDrain)).BeginInit(); @@ -383,6 +385,7 @@ private void InitializeComponent() ((System.ComponentModel.ISupportInitialize)(this.nudChartLevelEvenMin)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.numericUpDownMaxBreedingSug)).BeginInit(); this.groupBox5.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.NudWildDinoCharacterFoodDrainMultiplier)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.NudWildDinoTorporDrainMultiplier)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.nudDinoCharacterFoodDrainEvent)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.nudTamingSpeedEvent)).BeginInit(); @@ -459,7 +462,6 @@ private void InitializeComponent() ((System.ComponentModel.ISupportInitialize)(this.nudWaitBeforeScreenCapture)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.nudWhiteThreshold)).BeginInit(); this.panel1.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)(this.NudWildDinoCharacterFoodDrainMultiplier)).BeginInit(); this.SuspendLayout(); // // groupBoxMultiplier @@ -1503,6 +1505,39 @@ private void InitializeComponent() this.groupBox5.TabStop = false; this.groupBox5.Text = "Taming-Multiplier"; // + // NudWildDinoCharacterFoodDrainMultiplier + // + this.NudWildDinoCharacterFoodDrainMultiplier.DecimalPlaces = 6; + this.NudWildDinoCharacterFoodDrainMultiplier.ForeColor = System.Drawing.SystemColors.WindowText; + this.NudWildDinoCharacterFoodDrainMultiplier.Location = new System.Drawing.Point(183, 71); + this.NudWildDinoCharacterFoodDrainMultiplier.Maximum = new decimal(new int[] { + 10000, + 0, + 0, + 0}); + this.NudWildDinoCharacterFoodDrainMultiplier.Name = "NudWildDinoCharacterFoodDrainMultiplier"; + this.NudWildDinoCharacterFoodDrainMultiplier.NeutralNumber = new decimal(new int[] { + 0, + 0, + 0, + 0}); + this.NudWildDinoCharacterFoodDrainMultiplier.Size = new System.Drawing.Size(72, 20); + this.NudWildDinoCharacterFoodDrainMultiplier.TabIndex = 4; + this.NudWildDinoCharacterFoodDrainMultiplier.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + // + // label69 + // + this.label69.AutoSize = true; + this.label69.Location = new System.Drawing.Point(10, 73); + this.label69.Name = "label69"; + this.label69.Size = new System.Drawing.Size(186, 13); + this.label69.TabIndex = 7; + this.label69.Text = "WildDinoCharacterFoodDrainMultiplier"; + // // label67 // this.label67.AutoSize = true; @@ -1652,7 +1687,7 @@ private void InitializeComponent() // // label15 // - this.label15.Location = new System.Drawing.Point(451, 575); + this.label15.Location = new System.Drawing.Point(450, 548); this.label15.Name = "label15"; this.label15.Size = new System.Drawing.Size(289, 77); this.label15.TabIndex = 9; @@ -1833,15 +1868,17 @@ private void InitializeComponent() // this.tabPageMultipliers.AllowDrop = true; this.tabPageMultipliers.AutoScroll = true; + this.tabPageMultipliers.Controls.Add(this.TbRemoteServerSettingsUri); + this.tabPageMultipliers.Controls.Add(this.BtSettingsToClipboard); + this.tabPageMultipliers.Controls.Add(this.btExportMultipliers); + this.tabPageMultipliers.Controls.Add(this.BtRemoteServerSettingsUri); this.tabPageMultipliers.Controls.Add(this.CbKeepMultipliersForNewLibrary); this.tabPageMultipliers.Controls.Add(this.BtAutoImportLocalSettings); this.tabPageMultipliers.Controls.Add(this.panel3); this.tabPageMultipliers.Controls.Add(this.BtImportSettingsSelectFile); this.tabPageMultipliers.Controls.Add(this.CbAtlasSettings); - this.tabPageMultipliers.Controls.Add(this.BtSettingsToClipboard); this.tabPageMultipliers.Controls.Add(this.groupBox29); this.tabPageMultipliers.Controls.Add(this.label34); - this.tabPageMultipliers.Controls.Add(this.btExportMultipliers); this.tabPageMultipliers.Controls.Add(this.groupBox18); this.tabPageMultipliers.Controls.Add(this.label27); this.tabPageMultipliers.Controls.Add(this.cbSingleplayerSettings); @@ -1876,7 +1913,7 @@ private void InitializeComponent() // BtAutoImportLocalSettings // this.BtAutoImportLocalSettings.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(192)))), ((int)(((byte)(255)))), ((int)(((byte)(192))))); - this.BtAutoImportLocalSettings.Location = new System.Drawing.Point(407, 642); + this.BtAutoImportLocalSettings.Location = new System.Drawing.Point(407, 628); this.BtAutoImportLocalSettings.Name = "BtAutoImportLocalSettings"; this.BtAutoImportLocalSettings.Size = new System.Drawing.Size(152, 23); this.BtAutoImportLocalSettings.TabIndex = 17; @@ -1918,7 +1955,7 @@ private void InitializeComponent() // // BtImportSettingsSelectFile // - this.BtImportSettingsSelectFile.Location = new System.Drawing.Point(565, 642); + this.BtImportSettingsSelectFile.Location = new System.Drawing.Point(565, 628); this.BtImportSettingsSelectFile.Name = "BtImportSettingsSelectFile"; this.BtImportSettingsSelectFile.Size = new System.Drawing.Size(167, 23); this.BtImportSettingsSelectFile.TabIndex = 15; @@ -1980,7 +2017,7 @@ private void InitializeComponent() // // label34 // - this.label34.Location = new System.Drawing.Point(404, 676); + this.label34.Location = new System.Drawing.Point(404, 682); this.label34.Name = "label34"; this.label34.Size = new System.Drawing.Size(338, 34); this.label34.TabIndex = 10; @@ -2031,7 +2068,7 @@ private void InitializeComponent() // this.label27.AutoSize = true; this.label27.Font = new System.Drawing.Font("Microsoft Sans Serif", 16F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label27.Location = new System.Drawing.Point(408, 576); + this.label27.Location = new System.Drawing.Point(407, 562); this.label27.Name = "label27"; this.label27.Size = new System.Drawing.Size(37, 26); this.label27.TabIndex = 12; @@ -2110,7 +2147,7 @@ private void InitializeComponent() // // buttonEventToDefault // - this.buttonEventToDefault.Location = new System.Drawing.Point(604, 547); + this.buttonEventToDefault.Location = new System.Drawing.Point(512, 137); this.buttonEventToDefault.Name = "buttonEventToDefault"; this.buttonEventToDefault.Size = new System.Drawing.Size(136, 23); this.buttonEventToDefault.TabIndex = 8; @@ -2147,7 +2184,7 @@ private void InitializeComponent() this.tabPageGeneral.Location = new System.Drawing.Point(4, 22); this.tabPageGeneral.Name = "tabPageGeneral"; this.tabPageGeneral.Padding = new System.Windows.Forms.Padding(3); - this.tabPageGeneral.Size = new System.Drawing.Size(750, 722); + this.tabPageGeneral.Size = new System.Drawing.Size(750, 744); this.tabPageGeneral.TabIndex = 0; this.tabPageGeneral.Text = "General"; this.tabPageGeneral.UseVisualStyleBackColor = true; @@ -2602,7 +2639,7 @@ private void InitializeComponent() this.tabPageInfoGraphic.Controls.Add(this.label50); this.tabPageInfoGraphic.Location = new System.Drawing.Point(4, 22); this.tabPageInfoGraphic.Name = "tabPageInfoGraphic"; - this.tabPageInfoGraphic.Size = new System.Drawing.Size(750, 722); + this.tabPageInfoGraphic.Size = new System.Drawing.Size(750, 744); this.tabPageInfoGraphic.TabIndex = 7; this.tabPageInfoGraphic.Text = "Info Graphic"; this.tabPageInfoGraphic.UseVisualStyleBackColor = true; @@ -2860,7 +2897,7 @@ private void InitializeComponent() this.tabPageImportSavegame.Location = new System.Drawing.Point(4, 22); this.tabPageImportSavegame.Name = "tabPageImportSavegame"; this.tabPageImportSavegame.Padding = new System.Windows.Forms.Padding(3); - this.tabPageImportSavegame.Size = new System.Drawing.Size(750, 722); + this.tabPageImportSavegame.Size = new System.Drawing.Size(750, 744); this.tabPageImportSavegame.TabIndex = 2; this.tabPageImportSavegame.Text = "Import Savegame"; this.tabPageImportSavegame.UseVisualStyleBackColor = true; @@ -3113,7 +3150,7 @@ private void InitializeComponent() this.tabPageImportExported.Location = new System.Drawing.Point(4, 22); this.tabPageImportExported.Name = "tabPageImportExported"; this.tabPageImportExported.Padding = new System.Windows.Forms.Padding(3); - this.tabPageImportExported.Size = new System.Drawing.Size(750, 722); + this.tabPageImportExported.Size = new System.Drawing.Size(750, 744); this.tabPageImportExported.TabIndex = 3; this.tabPageImportExported.Text = "Import Exported"; this.tabPageImportExported.UseVisualStyleBackColor = true; @@ -3622,7 +3659,7 @@ private void InitializeComponent() this.tabPageTimers.Location = new System.Drawing.Point(4, 22); this.tabPageTimers.Name = "tabPageTimers"; this.tabPageTimers.Padding = new System.Windows.Forms.Padding(3); - this.tabPageTimers.Size = new System.Drawing.Size(750, 722); + this.tabPageTimers.Size = new System.Drawing.Size(750, 744); this.tabPageTimers.TabIndex = 6; this.tabPageTimers.Text = "Timers"; this.tabPageTimers.UseVisualStyleBackColor = true; @@ -3706,7 +3743,7 @@ private void InitializeComponent() this.customSCCustom.Location = new System.Drawing.Point(6, 139); this.customSCCustom.Name = "customSCCustom"; this.customSCCustom.Size = new System.Drawing.Size(401, 23); - this.customSCCustom.SoundFile = null; + this.customSCCustom.SoundFile = ""; this.customSCCustom.TabIndex = 4; // // customSCWakeup @@ -3714,7 +3751,7 @@ private void InitializeComponent() this.customSCWakeup.Location = new System.Drawing.Point(6, 81); this.customSCWakeup.Name = "customSCWakeup"; this.customSCWakeup.Size = new System.Drawing.Size(401, 23); - this.customSCWakeup.SoundFile = ""; + this.customSCWakeup.SoundFile = null; this.customSCWakeup.TabIndex = 2; // // customSCBirth @@ -3722,7 +3759,7 @@ private void InitializeComponent() this.customSCBirth.Location = new System.Drawing.Point(6, 110); this.customSCBirth.Name = "customSCBirth"; this.customSCBirth.Size = new System.Drawing.Size(401, 23); - this.customSCBirth.SoundFile = ""; + this.customSCBirth.SoundFile = null; this.customSCBirth.TabIndex = 3; // // customSCStarving @@ -3730,7 +3767,7 @@ private void InitializeComponent() this.customSCStarving.Location = new System.Drawing.Point(6, 52); this.customSCStarving.Name = "customSCStarving"; this.customSCStarving.Size = new System.Drawing.Size(401, 23); - this.customSCStarving.SoundFile = null; + this.customSCStarving.SoundFile = ""; this.customSCStarving.TabIndex = 1; // // label20 @@ -3748,7 +3785,7 @@ private void InitializeComponent() this.tabPageOverlay.Location = new System.Drawing.Point(4, 22); this.tabPageOverlay.Name = "tabPageOverlay"; this.tabPageOverlay.Padding = new System.Windows.Forms.Padding(3); - this.tabPageOverlay.Size = new System.Drawing.Size(750, 722); + this.tabPageOverlay.Size = new System.Drawing.Size(750, 744); this.tabPageOverlay.TabIndex = 5; this.tabPageOverlay.Text = "Overlay"; this.tabPageOverlay.UseVisualStyleBackColor = true; @@ -4128,7 +4165,7 @@ private void InitializeComponent() this.tabPageOCR.Location = new System.Drawing.Point(4, 22); this.tabPageOCR.Name = "tabPageOCR"; this.tabPageOCR.Padding = new System.Windows.Forms.Padding(3); - this.tabPageOCR.Size = new System.Drawing.Size(750, 722); + this.tabPageOCR.Size = new System.Drawing.Size(750, 744); this.tabPageOCR.TabIndex = 4; this.tabPageOCR.Text = "OCR"; this.tabPageOCR.UseVisualStyleBackColor = true; @@ -4449,38 +4486,22 @@ private void InitializeComponent() this.panel1.Size = new System.Drawing.Size(758, 30); this.panel1.TabIndex = 12; // - // label69 + // BtRemoteServerSettingsUri // - this.label69.AutoSize = true; - this.label69.Location = new System.Drawing.Point(10, 73); - this.label69.Name = "label69"; - this.label69.Size = new System.Drawing.Size(186, 13); - this.label69.TabIndex = 7; - this.label69.Text = "WildDinoCharacterFoodDrainMultiplier"; + this.BtRemoteServerSettingsUri.Location = new System.Drawing.Point(565, 657); + this.BtRemoteServerSettingsUri.Name = "BtRemoteServerSettingsUri"; + this.BtRemoteServerSettingsUri.Size = new System.Drawing.Size(167, 23); + this.BtRemoteServerSettingsUri.TabIndex = 19; + this.BtRemoteServerSettingsUri.Text = "Import remote settings"; + this.BtRemoteServerSettingsUri.UseVisualStyleBackColor = true; + this.BtRemoteServerSettingsUri.Click += new System.EventHandler(this.BtRemoteServerSettingsUri_Click); // - // NudWildDinoCharacterFoodDrainMultiplier + // TbRemoteServerSettingsUri // - this.NudWildDinoCharacterFoodDrainMultiplier.DecimalPlaces = 6; - this.NudWildDinoCharacterFoodDrainMultiplier.ForeColor = System.Drawing.SystemColors.WindowText; - this.NudWildDinoCharacterFoodDrainMultiplier.Location = new System.Drawing.Point(183, 71); - this.NudWildDinoCharacterFoodDrainMultiplier.Maximum = new decimal(new int[] { - 10000, - 0, - 0, - 0}); - this.NudWildDinoCharacterFoodDrainMultiplier.Name = "NudWildDinoCharacterFoodDrainMultiplier"; - this.NudWildDinoCharacterFoodDrainMultiplier.NeutralNumber = new decimal(new int[] { - 0, - 0, - 0, - 0}); - this.NudWildDinoCharacterFoodDrainMultiplier.Size = new System.Drawing.Size(72, 20); - this.NudWildDinoCharacterFoodDrainMultiplier.TabIndex = 4; - this.NudWildDinoCharacterFoodDrainMultiplier.Value = new decimal(new int[] { - 1, - 0, - 0, - 0}); + this.TbRemoteServerSettingsUri.Location = new System.Drawing.Point(407, 659); + this.TbRemoteServerSettingsUri.Name = "TbRemoteServerSettingsUri"; + this.TbRemoteServerSettingsUri.Size = new System.Drawing.Size(152, 20); + this.TbRemoteServerSettingsUri.TabIndex = 20; // // Settings // @@ -4535,6 +4556,7 @@ private void InitializeComponent() ((System.ComponentModel.ISupportInitialize)(this.numericUpDownMaxBreedingSug)).EndInit(); this.groupBox5.ResumeLayout(false); this.groupBox5.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.NudWildDinoCharacterFoodDrainMultiplier)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.NudWildDinoTorporDrainMultiplier)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.nudDinoCharacterFoodDrainEvent)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.nudTamingSpeedEvent)).EndInit(); @@ -4643,7 +4665,6 @@ private void InitializeComponent() ((System.ComponentModel.ISupportInitialize)(this.nudWaitBeforeScreenCapture)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.nudWhiteThreshold)).EndInit(); this.panel1.ResumeLayout(false); - ((System.ComponentModel.ISupportInitialize)(this.NudWildDinoCharacterFoodDrainMultiplier)).EndInit(); this.ResumeLayout(false); } @@ -4971,5 +4992,7 @@ private void InitializeComponent() private System.Windows.Forms.Label label68; private uiControls.Nud NudWildDinoCharacterFoodDrainMultiplier; private System.Windows.Forms.Label label69; + private System.Windows.Forms.Button BtRemoteServerSettingsUri; + private System.Windows.Forms.TextBox TbRemoteServerSettingsUri; } } \ No newline at end of file diff --git a/ARKBreedingStats/settings/Settings.cs b/ARKBreedingStats/settings/Settings.cs index 1a03ec68..ecac9b50 100644 --- a/ARKBreedingStats/settings/Settings.cs +++ b/ARKBreedingStats/settings/Settings.cs @@ -5,7 +5,10 @@ using System.Drawing; using System.IO; using System.Linq; +using System.Net.Http; using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; using System.Windows.Forms; using System.Windows.Threading; using ARKBreedingStats.importExportGun; @@ -24,6 +27,7 @@ public partial class Settings : Form public SettingsTabPages LastTabPageIndex; public bool LanguageChanged; public bool ColorRegionDisplayChanged; + private CancellationTokenSource _cancellationTokenSource; public Settings(CreatureCollection cc, SettingsTabPages page) { @@ -254,6 +258,7 @@ private void LoadSettings(CreatureCollection cc) nudBabyFoodConsumptionSpeedEvent.ValueSave = (decimal)multipliers.BabyFoodConsumptionSpeedMultiplier; #endregion + TbRemoteServerSettingsUri.Text = cc.ServerSettingsUriSource; checkBoxAutoSave.Checked = Properties.Settings.Default.autosave; chkCollectionSync.Checked = Properties.Settings.Default.syncCollection; NudWaitBeforeAutoLoad.ValueSave = Properties.Settings.Default.WaitBeforeAutoLoadMs; @@ -520,6 +525,7 @@ private void SaveSettings() _cc.serverMultipliersEvents.BabyFoodConsumptionSpeedMultiplier = (double)nudBabyFoodConsumptionSpeedEvent.Value; #endregion + _cc.ServerSettingsUriSource = string.IsNullOrEmpty(TbRemoteServerSettingsUri.Text) ? null : TbRemoteServerSettingsUri.Text; Properties.Settings.Default.autosave = checkBoxAutoSave.Checked; Properties.Settings.Default.syncCollection = chkCollectionSync.Checked; Properties.Settings.Default.WaitBeforeAutoLoadMs = (int)NudWaitBeforeAutoLoad.Value; @@ -1693,5 +1699,82 @@ private void BtAutoImportLocalSettings_Click(object sender, EventArgs e) if (localConfigPaths[importIndex].Item2 == Ark.Game.ASA) RbGameAsa.Checked = true; else RbGameAse.Checked = true; } + + private async void BtRemoteServerSettingsUri_Click(object sender, EventArgs e) + { + var uri = TbRemoteServerSettingsUri.Text; + if (string.IsNullOrEmpty(uri)) + { + MessageBoxes.ShowMessageBox("No url for a server settings file given. Enter the url to the text box near the button you just clicked."); + return; + } + + if (_cancellationTokenSource != null) + { + _cancellationTokenSource.Cancel(); + return; + } + + try + { + var httpClient = FileService.GetHttpClient; + _cancellationTokenSource = new CancellationTokenSource(); + BtRemoteServerSettingsUri.Text = "Cancel loading"; + string settingsText = null; + using (var result = await httpClient.GetAsync(uri, _cancellationTokenSource.Token)) + { + if (!result.IsSuccessStatusCode) + { + MessageBoxes.ShowMessageBox( + $"Error when trying to load settings from{Environment.NewLine}{uri}{Environment.NewLine}StatusCode {(int)result.StatusCode}: {result.ReasonPhrase}"); + return; + } + + settingsText = await result.Content.ReadAsStringAsync(); + } + + if (string.IsNullOrEmpty(settingsText)) + { + MessageBoxes.ShowMessageBox( + $"The specified source{Environment.NewLine}{uri}{Environment.NewLine}contains not text, nothing was imported."); + return; + } + + if (MessageBox.Show($"Apply the settings of the downloaded file?{Environment.NewLine}{uri}", + "Use downloaded settings?", + MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes) + { + ExtractSettingsFromText(settingsText, true); + } + + } + catch (InvalidOperationException ex) + { + MessageBoxes.ShowMessageBox( + $"The given url{Environment.NewLine}{uri}{Environment.NewLine}is not valid.{Environment.NewLine}{ex.Message}", + "Invalid url"); + } + catch (TaskCanceledException ex) + { + if (_cancellationTokenSource?.IsCancellationRequested == true) + { + // request canceled by user + return; + } + MessageBoxes.ShowMessageBox( + $"The given url{Environment.NewLine}{uri}{Environment.NewLine}didn't respond fast enough (timeout), maybe the url is incorrect.{Environment.NewLine}{ex.Message}", + "Timeout when loading server settings"); + } + catch (Exception ex) + { + MessageBoxes.ExceptionMessageBox(ex, "Server settings file couldn't be loaded."); + } + finally + { + _cancellationTokenSource?.Dispose(); + _cancellationTokenSource = null; + BtRemoteServerSettingsUri.Text = "Load remote settings"; + } + } } } diff --git a/ARKBreedingStats/species/Species.cs b/ARKBreedingStats/species/Species.cs index 87857ca7..ab707c77 100644 --- a/ARKBreedingStats/species/Species.cs +++ b/ARKBreedingStats/species/Species.cs @@ -161,6 +161,7 @@ private void Initialize(StreamingContext _) var fullStatsRawLength = fullStatsRaw?.Length ?? 0; + _skipWildLevelStatsWithServerSettings = skipWildLevelStats; usedStats = 0; StatImprintMultipliers = statImprintMult ?? StatImprintMultipliersDefaultAse.ToArray(); @@ -173,6 +174,7 @@ private void Initialize(StreamingContext _) if (altBaseStatsRaw?.ContainsKey(s) ?? false) altStats[s] = new CreatureStat(); + var usesStat = false; completeRaws[s] = new double[] { 0, 0, 0, 0, 0 }; if (fullStatsRawLength > s && fullStatsRaw[s] != null) { @@ -183,11 +185,16 @@ private void Initialize(StreamingContext _) completeRaws[s][i] = fullStatsRaw[s]?[i] ?? 0; if (i == 0 && fullStatsRaw[s][0] > 0) { - usedStats |= (1 << s); + usesStat = true; } } } } + var statBit = (1 << s); + if (usesStat) + usedStats |= statBit; + else + _skipWildLevelStatsWithServerSettings |= statBit; } if (fullStatsRawLength != -0) @@ -218,8 +225,6 @@ private void Initialize(StreamingContext _) boneDamageAdjusters = boneDamageAdjustersCleanedUp; } - _skipWildLevelStatsWithServerSettings = skipWildLevelStats; - IsDomesticable = (taming != null && (taming.nonViolent || taming.violent)) || (breeding != null && (breeding.incubationTime > 0 || breeding.gestationTime > 0)); } diff --git a/ARKBreedingStats/uiControls/StatIO.cs b/ARKBreedingStats/uiControls/StatIO.cs index e6f30777..728364f6 100644 --- a/ARKBreedingStats/uiControls/StatIO.cs +++ b/ARKBreedingStats/uiControls/StatIO.cs @@ -1,8 +1,10 @@ using System; using System.Drawing; using System.Windows.Forms; +using System.Windows.Input; using System.Windows.Threading; using ARKBreedingStats.utils; +using Cursors = System.Windows.Forms.Cursors; namespace ARKBreedingStats { @@ -378,24 +380,29 @@ private void labelWildLevel_Click(object sender, EventArgs e) { OnClick(e); - if (LevelMut > 1) - { - LevelWild += 2; - LevelMut -= 2; - LevelChangedDebouncer(); - } + var levelDelta = LevelDeltaMutationShift(LevelMut); + if (levelDelta <= 0) return; + LevelWild += levelDelta; + LevelMut -= levelDelta; + LevelChangedDebouncer(); } private void labelMutatedLevel_Click(object sender, EventArgs e) { OnClick(e); - if (LevelWild > 1) - { - LevelWild -= 2; - LevelMut += 2; - LevelChangedDebouncer(); - } + var levelDelta = LevelDeltaMutationShift(LevelWild); + if (levelDelta <= 0) return; + LevelWild -= levelDelta; + LevelMut += levelDelta; + LevelChangedDebouncer(); + } + + private int LevelDeltaMutationShift(int remainingLevel) + { + var levelDelta = Keyboard.Modifiers.HasFlag(System.Windows.Input.ModifierKeys.Shift) ? 10 : 2; + if (remainingLevel < levelDelta) levelDelta = (remainingLevel / 2) * 2; + return levelDelta; } private void labelDomLevel_Click(object sender, EventArgs e) diff --git a/setup.iss b/setup.iss index 4653a5c8..08c4cf9a 100644 --- a/setup.iss +++ b/setup.iss @@ -89,6 +89,7 @@ Source: "{#ReleaseDir}\tr\*"; DestDir: "{app}\tr\"; Excludes: "*.pdb,*.xml"; Fla Source: "{#ReleaseDir}\zh\*"; DestDir: "{app}\zh\"; Excludes: "*.pdb,*.xml"; Flags: ignoreversion skipifsourcedoesntexist Source: "{#ReleaseDir}\_manifest.json"; DestDir: "{localappdata}\{#AppName}\"; Flags: ignoreversion Source: "{#ReleaseDir}\json\*.json"; DestDir: "{localappdata}\{#AppName}\json\"; Flags: ignoreversion +Source: "{#ReleaseDir}\json\*.txt"; DestDir: "{localappdata}\{#AppName}\json\"; Flags: ignoreversion Source: "{#ReleaseDir}\json\values\values.json"; DestDir: "{localappdata}\{#AppName}\json\values\"; Flags: ignoreversion Source: "{#ReleaseDir}\json\values\ASA-values.json"; DestDir: "{localappdata}\{#AppName}\json\values\"; Flags: ignoreversion Source: "{#ReleaseDir}\json\values\_manifest.json"; DestDir: "{localappdata}\{#AppName}\json\values\"; Flags: ignoreversion