From f655a4db3f8b9447c8c6ccb91a6fef346e704c43 Mon Sep 17 00:00:00 2001 From: LeeTwentyThree <31892011+LeeTwentyThree@users.noreply.github.com> Date: Sat, 4 Nov 2023 15:25:52 -0400 Subject: [PATCH 1/8] Update AUTHORS.md --- AUTHORS.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/AUTHORS.md b/AUTHORS.md index 4d2450b3..fc3478c7 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -3,15 +3,15 @@ We thank all of the following individuals for their contributions to Nautilus. T | Name | Picture | Commits | Name | Picture | Commits | Name | Picture | Commits | | ---- | --------------- | ------ | ---- | --------------- | ------ | ---- | --------------- | ------ | -| [MrPurple6411](https://github.com/MrPurple6411) | | 433 | [PrimeSonic](https://github.com/PrimeSonic) | | 312 | [Metious](https://github.com/Metious) | | 297 | +| [MrPurple6411](https://github.com/MrPurple6411) | | 451 | [PrimeSonic](https://github.com/PrimeSonic) | | 312 | [Metious](https://github.com/Metious) | | 309 | | [toebeann](https://github.com/toebeann) | | 228 | [ahk1221](https://github.com/ahk1221) | | 212 | [Alexejhero](https://github.com/Alexejhero) | | 207 | -| [LeeTwentyThree](https://github.com/LeeTwentyThree) | | 122 | [zorgesho](https://github.com/zorgesho) | | 42 | [JKohlman](https://github.com/JKohlman) | | 37 | +| [LeeTwentyThree](https://github.com/LeeTwentyThree) | | 126 | [zorgesho](https://github.com/zorgesho) | | 42 | [JKohlman](https://github.com/JKohlman) | | 37 | | [K07H](https://github.com/K07H) | | 22 | [Vlad-00003](https://github.com/Vlad-00003) | | 11 | [EckoTheBat](https://github.com/EckoTheBat) | | 11 | -| [github-actions[bot]](https://github.com/apps/github-actions) | | 6 | [Cattlesquat](https://github.com/Cattlesquat) | | 5 | [DingoDjango](https://github.com/DingoDjango) | | 4 | +| [github-actions[bot]](https://github.com/apps/github-actions) | | 8 | [Cattlesquat](https://github.com/Cattlesquat) | | 5 | [DingoDjango](https://github.com/DingoDjango) | | 4 | | [celvro](https://github.com/celvro) | | 4 | [NeisesMike](https://github.com/NeisesMike) | | 3 | [VELD-Dev](https://github.com/VELD-Dev) | | 3 | | [vlyon](https://github.com/vlyon) | | 3 | [EldritchCarMaker](https://github.com/EldritchCarMaker) | | 3 | [jonahnm](https://github.com/jonahnm) | | 3 | -| [brett-taylor](https://github.com/brett-taylor) | | 2 | [RamuneNeptune](https://github.com/RamuneNeptune) | | 2 | [DeadMor0z](https://github.com/DeadMor0z) | | 1 | -| [SamuramongeDev](https://github.com/SamuramongeDev) | | 1 | +| [brett-taylor](https://github.com/brett-taylor) | | 2 | [RamuneNeptune](https://github.com/RamuneNeptune) | | 2 | [tinyhoot](https://github.com/tinyhoot) | | 2 | +| [DeadMor0z](https://github.com/DeadMor0z) | | 1 | [SamuramongeDev](https://github.com/SamuramongeDev) | | 1 | If you notice a problem with this file, feel free to report an issue in the repository. From f4ec60064cf9f4d59c8f270adfac1386c6a548ec Mon Sep 17 00:00:00 2001 From: Metious <71298690+Metious@users.noreply.github.com> Date: Tue, 14 Nov 2023 21:05:47 +0330 Subject: [PATCH 2/8] fix: Safety measures for localization registration (#496) Added safety checks for localization registration --- Nautilus/Handlers/LanguageHandler.cs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/Nautilus/Handlers/LanguageHandler.cs b/Nautilus/Handlers/LanguageHandler.cs index 2f8fc85d..ef75ff58 100644 --- a/Nautilus/Handlers/LanguageHandler.cs +++ b/Nautilus/Handlers/LanguageHandler.cs @@ -45,7 +45,22 @@ public static void RegisterLocalizationFolder(string languageFolderName = "Local foreach (var file in Directory.GetFiles(path)) { - var content = JsonConvert.DeserializeObject>(File.ReadAllText(file)); + if (Path.GetExtension(file) != ".json") + { + continue; + } + + // I hate this + Dictionary content = null; + try + { + content = JsonConvert.DeserializeObject>(File.ReadAllText(file)); + } + catch (Exception e) + { + InternalLogger.Error($"Exception caught while trying to deserialize localization file at path: '{file}'. Exception: {e}"); + } + if (content is null) { InternalLogger.Warn($"Localization file '{file}' is empty, skipping registration."); From 661b32f967776832a9556160e5f7ef99dbdabab0 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 24 Nov 2023 08:52:17 +0000 Subject: [PATCH 3/8] @Govorunb has signed the CLA in SubnauticaModding/Nautilus#505 --- CLA/Signatures.json | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CLA/Signatures.json b/CLA/Signatures.json index e27f4706..b5d0b204 100644 --- a/CLA/Signatures.json +++ b/CLA/Signatures.json @@ -55,6 +55,14 @@ "created_at": "2023-09-25T14:00:10Z", "repoId": 123711758, "pullRequestNo": 468 + }, + { + "name": "Govorunb", + "id": 3830522, + "comment_id": 1825332180, + "created_at": "2023-11-24T08:52:03Z", + "repoId": 123711758, + "pullRequestNo": 505 } ] } \ No newline at end of file From 647781677478c70062dfbb8730f771272a54727d Mon Sep 17 00:00:00 2001 From: MrPurple6411 Date: Fri, 1 Dec 2023 17:26:46 -0700 Subject: [PATCH 4/8] feat: UploadHelper Overhaul/Fixing BepInExPluginVersion (#503) * UploadHelper Overhaul/Fixing BepInExPluginVersion * Fix for spaces in path --- Example mod/Example mod.csproj | 89 +++++----- Nautilus.sln | 4 +- Nautilus/Nautilus.csproj | 4 +- PostBuild.targets | 4 +- UploadHelper/Program.cs | 301 ++++++++++++++++++++++----------- Version.targets | 2 + 6 files changed, 259 insertions(+), 145 deletions(-) diff --git a/Example mod/Example mod.csproj b/Example mod/Example mod.csproj index fa1791b4..5b4e2d93 100644 --- a/Example mod/Example mod.csproj +++ b/Example mod/Example mod.csproj @@ -1,47 +1,48 @@ - - - - net472 - false - false - Nautilus.Examples - Nautilus.Example - true - true - AnyCPU - latest - SN.STABLE;BZ.STABLE - AnyCPU - Copyright © 2023 - false - false - - - - bin\SN.STABLE\ - SUBNAUTICA;SUBNAUTICA_STABLE - - - bin\BZ.STABLE\ - BELOWZERO;BELOWZERO_STABLE - - - - False - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + + + net472 + false + false + Nautilus.Examples + Nautilus.Example + $(VersionPrefix).$(SuffixNumber) + true + true + AnyCPU + latest + SN.STABLE;BZ.STABLE + AnyCPU + Copyright © 2023 + false + false + + + bin\SN.STABLE\ + SUBNAUTICA;SUBNAUTICA_STABLE + + + bin\BZ.STABLE\ + BELOWZERO;BELOWZERO_STABLE + - + + False + - - + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + \ No newline at end of file diff --git a/Nautilus.sln b/Nautilus.sln index 1a386e0f..d8f313ae 100644 --- a/Nautilus.sln +++ b/Nautilus.sln @@ -13,10 +13,12 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{5152F028-6D03-43C0-88C5-986313017D4F}" ProjectSection(SolutionItems) = preProject common.props = common.props + Directory.Build.props = Directory.Build.props + PostBuild.targets = PostBuild.targets Version.targets = Version.targets EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UploadHelper", "UploadHelper\UploadHelper.csproj", "{1D6AED20-87CC-4756-8E6A-1E8A10E16EB1}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UploadHelper", "UploadHelper\UploadHelper.csproj", "{1D6AED20-87CC-4756-8E6A-1E8A10E16EB1}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/Nautilus/Nautilus.csproj b/Nautilus/Nautilus.csproj index 8123602d..ae1db35c 100644 --- a/Nautilus/Nautilus.csproj +++ b/Nautilus/Nautilus.csproj @@ -1,4 +1,4 @@ - + @@ -8,7 +8,7 @@ Nautilus Nautilus com.snmodding.nautilus - $(VersionPrefix) + $(VersionPrefix).$(SuffixNumber) 11 true true diff --git a/PostBuild.targets b/PostBuild.targets index 6b3968e5..52552125 100644 --- a/PostBuild.targets +++ b/PostBuild.targets @@ -1,11 +1,11 @@ - + Nautilus $(OutDir)\plugins $([System.IO.Path]::Combine('$(PluginsDir)', '$(BuildPath)')) - $([System.IO.Path]::Combine('$(TargetDir)', 'Nautilus_$(ConfigurationName).zip')) + $([System.IO.Path]::Combine('$(TargetDir)', 'Nautilus_$(ConfigurationName)_$(BepInExPluginVersion).zip')) $([System.IO.Path]::Combine('$(OutDir)', 'TemporaryDir')) $([System.IO.Path]::Combine('$(TemporaryDir)', 'Build')) diff --git a/UploadHelper/Program.cs b/UploadHelper/Program.cs index e8022ae6..2ae9414a 100644 --- a/UploadHelper/Program.cs +++ b/UploadHelper/Program.cs @@ -8,10 +8,15 @@ internal static class Program private const string VersionPrefixStart = ""; private const string VersionPrefixEnd = ""; + private const string SuffixNumberStart = ""; + private const string SuffixNumberEnd = ""; private const string VersionSuffixStart = ""; private const string VersionSuffixEnd = ""; + private static string _versionPrefix; + private static int _versionSuffix; + private static Version _version; - private static string[] _uploadPageURLs = new string[] + private static readonly string[] _uploadPageURLs = new string[] { "https://github.com/SubnauticaModding/Nautilus/releases", "https://www.submodica.xyz/mods/sn1/250", @@ -22,171 +27,275 @@ internal static class Program public static void Main(string[] args) { + Console.Clear(); // essential variables - _nautilusDirectory = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "..", "..", ".."); - - // greeting - Console.WriteLine("Welcome to the Upload Helper for Nautilus. This program should become obsolete as soon as we set up a proper build deployment system.\n"); + _nautilusDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + var solutionPath = ""; + while (_nautilusDirectory != null) + { + var file = Path.Combine(_nautilusDirectory, "Nautilus.sln"); + if (File.Exists(file)) + { + solutionPath = file; + break; + } - Console.WriteLine("Press ENTER to begin..."); - Console.ReadLine(); + _nautilusDirectory = Directory.GetParent(_nautilusDirectory)?.FullName; + } - // get old version - Console.WriteLine("First of all, we need to determine the version string."); - var oldVersion = GetCurrentVersionString(); - Console.WriteLine($"I think the current version string is {oldVersion} (suffixes such as the pre-release number might not be shown here), but it's a good idea to double check.\n"); - Console.WriteLine("When you press enter, I will open https://www.submodica.xyz/mods/sn1/246 and https://github.com/SubnauticaModding/Nautilus/releases in your browser so you can find the version string that is currently uploaded to the internet."); - Console.WriteLine("If you don't want this, just type something before you hit enter."); - if (string.IsNullOrEmpty(Console.ReadLine())) + if (string.IsNullOrWhiteSpace(solutionPath)) { - Process.Start("explorer", "https://www.submodica.xyz/mods/sn1/250"); - Thread.Sleep(1000); - Process.Start("explorer", "https://github.com/SubnauticaModding/Nautilus/releases"); + Console.WriteLine($"Could not find the Nautilus solution in any parent directory."); + Console.ReadLine(); + return; } - // determine new version - - Console.WriteLine("Please write the NEW version number here (do NOT include the pre-release suffix): "); - var versionPrefix = Console.ReadLine(); - if (versionPrefix != null && versionPrefix.StartsWith("v")) + var nautilusProjectPath = Path.Combine(_nautilusDirectory, "Nautilus", "Nautilus.csproj"); + if (!File.Exists(nautilusProjectPath)) { - Console.WriteLine("Hm, why does it start with a V? Are you sure you meant to do that? If not, type R and we can retry that."); - var line = Console.ReadLine(); - if (line != null && line.ToLower() == "r") - { - Console.Write("Version number: "); - versionPrefix = Console.ReadLine(); - } + Console.WriteLine($"Could not find the Nautilus project at {nautilusProjectPath}"); + Console.ReadLine(); + return; } - Console.WriteLine("\nAnd now, if applicable, send the pre-release number (or leave empty): "); - string prereleaseNum = Console.ReadLine(); - string versionString = versionPrefix; + // greeting + Console.WriteLine("Welcome to the Upload Helper for Nautilus. \nThis program should become obsolete as soon as we set up a proper build deployment system.\n"); - if (!string.IsNullOrEmpty(prereleaseNum)) + if (!Ask("Do you want to begin? (y/n)")) { - versionString += "-pre." + prereleaseNum; - Console.WriteLine($"\nOh, you want to add \"pre.{prereleaseNum}\" to the version suffix? Sure, just remember we have to remove that when making the builds that we distribute."); - Console.WriteLine("If you are wondering why, that is because the BepInEx plugin."); + Console.Clear(); + Console.WriteLine("Alright, goodbye!"); + return; } - Console.WriteLine($"\nAlright, thanks! We’ll use {versionString} for this release."); - - SetCurrentVersionString(versionPrefix, "pre." + prereleaseNum); - - Console.WriteLine("\nThe Version.targets file was automatically updated. Remember that we have to fix that later."); - Console.WriteLine("\nNow, let's work on getting the NuGet package up and running."); + Console.Clear(); - Console.WriteLine("I should warn you now that you’ll need to log in to upload your update (for security reasons)." + - "\nPlease contact an administrator if you need help, otherwise we’ll continue from here."); - - WalkThroughNuGetSteps("SN.STABLE"); - - WalkThroughNuGetSteps("BZ.STABLE"); + // get old version + Console.WriteLine("First of all, we need to determine the version string."); - Console.WriteLine("\nRemember, these two versions you built are ONLY used for NUGET DEPENDENCIES. The version you have now should NOT be used in-game."); + Console.WriteLine("You can check https://github.com/SubnauticaModding/Nautilus/releases to find the version that is currently uploaded."); - Console.WriteLine("Alright, great, did everything work out? I’m having connection issues and I can’t see your responses, so I’ll assume that’s a yes."); + if (Ask("Do you want to open this in your browser? (y/n)")) + Process.Start("explorer", "https://github.com/SubnauticaModding/Nautilus/releases"); - SetCurrentVersionString(versionPrefix, null); + try + { + GetCurrentVersionString(); + } + catch (Exception e) + { + Console.WriteLine(e.Message); + Console.ReadLine(); + return; + } + var versionPrefix = _versionPrefix; + var suffixNumber = _versionSuffix; - Console.WriteLine("\nNow let’s work on getting this update pushed out to our users. First, we need to remove the prerelease tags from the assembly." + - "\nI’ve done that for you already. Now build for BOTH versions of the game."); + // determine new version + if (!Ask($"I think the current version string is {versionPrefix}.{suffixNumber}. Do you want to keep it? (y/n)")) + { + Console.WriteLine("Alright, we'll change it."); + Console.WriteLine("Please write the NEW 3 digit version number here (eg: 1.0.0) (do NOT include the pre-release suffix): "); + versionPrefix = RequestVersion(); + Version v; + while (!Version.TryParse(versionPrefix, out v) || v.Major < _version.Major || v.Minor < _version.Minor || v.Build < _version.Build) + { + Console.Clear(); + Console.WriteLine("That doesn't look like a valid version number or is less than the current version. Please try again."); + Console.WriteLine("Please write the NEW 3 digit version number here (eg: 1.0.0) (do NOT include the pre-release suffix): "); + versionPrefix = RequestVersion(); + } - Console.WriteLine("Press enter after you have ONCE AGAIN built the project for both SN.STABLE and BZ.STABLE."); + var isEqual = v.Major == _version.Major && v.Minor == _version.Minor && v.Build == _version.Build; + var response = isEqual || Ask("Do you want to add a pre-release suffix? (y/n)"); + while (response) + { + Console.WriteLine("What should the pre-release suffix be?"); + var prereleaseNum = Console.ReadLine(); + if (string.IsNullOrEmpty(prereleaseNum) || !int.TryParse(prereleaseNum, out suffixNumber)) + { + if (!Ask("That doesn't look like an intiger. Do you want to try again? (y/n)")) + break; + + Console.Clear(); + continue; + } + + if (isEqual && suffixNumber < _versionSuffix) + { + Console.Clear(); + Console.WriteLine("That's less than the current pre-release suffix. I'm not sure what you're trying to do, but I'm not going to let you do it."); + continue; + } + + if (suffixNumber < 0) + { + Console.Clear(); + Console.WriteLine("That's a negative number. I'm not sure what you're trying to do, but I'm not going to let you do it."); + continue; + } + + if (suffixNumber == 0) + { + Console.Clear(); + Console.WriteLine("That's a zero. I'm not sure what you're trying to do, but I'm not going to let you do it."); + if (!Ask("Do you want to try again? (y/n)")) + break; + continue; + } + + Console.Clear(); + if (Ask($"\nAdd \"{prereleaseNum}\" as the pre-release suffix? (y/n)")) + break; + Console.Clear(); + response = isEqual || Ask("Do you want to add a pre-release suffix? (y/n)"); + } + } - Console.ReadLine(); + Console.WriteLine($"\nAlright, thanks! We’ll use {versionPrefix}.{suffixNumber} for this release."); + SetCurrentVersionString(versionPrefix, suffixNumber); - Console.WriteLine("Press enter and I will open all the relevant pages where these mods should be uploaded in your browser."); + Console.WriteLine("\nNow, let's work on getting the NuGet packages up and running."); + Console.WriteLine("I should warn you now that you’ll need to log in to upload your update (for security reasons)." + + "\nPlease contact an administrator if you need help, otherwise we’ll continue from here."); - Console.ReadLine(); + RebuildNautilus(nautilusProjectPath); foreach (var url in _uploadPageURLs) { + if (!Ask($"Do you want to open {url} to upload? (y/n)")) + continue; + Console.WriteLine("Opening " + url + "..."); Process.Start("explorer", url); Thread.Sleep(500); + Console.Clear(); } + Console.Clear(); + Console.WriteLine("Congratulations, you're done!!!"); // END Console.ReadLine(); } - private static bool Ask(string prompt) + private static void RebuildNautilus(string projectPath) { - Console.WriteLine(prompt); - var l = Console.ReadLine(); - return !string.IsNullOrEmpty(l) && l.ToLower() == "y"; - } - - private static string VersionTargetsPath => Path.Combine(_nautilusDirectory, "Version.targets"); + // Start a new process + var process = new Process() + { + StartInfo = new ProcessStartInfo() + { + FileName = "cmd.exe", + RedirectStandardInput = true, + RedirectStandardOutput = true, + UseShellExecute = false + } + }; - private static void RebuildAuthorsTable() - { - var proc = new Process(); - proc.StartInfo.FileName = Path.Combine(_nautilusDirectory, "AuthorsTableGenerator", "AuthorTableGenerator.exe"); - proc.Start(); - proc.WaitForExit(); - proc.Close(); - } + process.Start(); - private static void WalkThroughNuGetSteps(string branch) - { - Console.WriteLine($"\nIn your IDE, switch to the {branch} build configuration, build the project, and then press ENTER in this window when you have finished."); + // Define the configurations to build + var configurations = new string[] { "SN.STABLE", "BZ.STABLE" }; - Console.ReadLine(); + // Execute the build with nuget restore for each configuration. + foreach (var configuration in configurations) + process.StandardInput.WriteLine($"dotnet build \"{projectPath}\" /restore /p:Configuration={configuration}"); - Console.WriteLine("All built and ready? When you press ENTER I will open the folder containing the built files."); + process.StandardInput.WriteLine("exit"); - Console.ReadLine(); + Console.WriteLine(process.StandardOutput.ReadToEnd()); + process.WaitForExit(); + Console.WriteLine("Now you need to upload the.nupkg files."); - Process.Start("explorer", Path.Combine(_nautilusDirectory, "Nautilus", "bin", branch)); + if (Ask("Do you want to open https://www.nuget.org/packages/manage/upload in your browser? (y/n)")) + Process.Start("explorer", "https://www.nuget.org/packages/manage/upload"); - Console.WriteLine("Got it? Now you need to upload the correct .nupkg file at https://www.nuget.org/packages/manage/upload. Press ENTER to open that in your browser."); + if (Ask($"Do you want to open the output paths in explorer? (y/n)")) + foreach (var configuration in configurations) + Process.Start("explorer", Path.Combine(_nautilusDirectory, "Nautilus", "bin", configuration)); + Console.WriteLine("Press enter to continue."); Console.ReadLine(); + } + + private static string RequestVersion() + { + var versionPrefix = Console.ReadLine(); + if (!string.IsNullOrWhiteSpace(versionPrefix) && versionPrefix.StartsWith("v")) + { + Console.WriteLine("Hm, why does it start with a V? Are you sure you meant to do that? If not, type R and we can retry that."); + var line = Console.ReadLine(); + if (line != null && line.ToLower() == "r") + { + Console.Write("Version number: "); + versionPrefix = Console.ReadLine(); + } + } + else if (string.IsNullOrWhiteSpace(versionPrefix)) + { + Console.WriteLine("You didn't write anything. I'll assume you want to keep the current version number."); + versionPrefix = _versionPrefix; + } + + return versionPrefix; + } - Process.Start("explorer", "https://www.nuget.org/packages/manage/upload"); + private static bool Ask(string prompt) + { + Console.WriteLine(prompt); + var l = Console.ReadLine(); + while (string.IsNullOrWhiteSpace(l) || (l.ToLower() != "y" && l.ToLower() != "n")) + { + Console.WriteLine("Please answer with y or n."); + Console.WriteLine(prompt); + l = Console.ReadLine(); + } + return l.ToLower() == "y"; } - private static string GetCurrentVersionString() + private static string VersionTargetsPath => Path.Combine(_nautilusDirectory, "Version.targets"); + + private static void GetCurrentVersionString() { var text = File.ReadAllText(VersionTargetsPath); var prefixStartIndex = text.IndexOf(VersionPrefixStart) + VersionPrefixStart.Length; var prefixLength = text.IndexOf(VersionPrefixEnd) - prefixStartIndex; - string prefix = text.Substring(prefixStartIndex, prefixLength); + var prefix = text.Substring(prefixStartIndex, prefixLength); string suffix = null; - if (text.Contains(VersionSuffixStart)) + if (text.Contains(SuffixNumberStart)) { - var suffixStartIndex = text.IndexOf(VersionSuffixStart) + VersionSuffixStart.Length; - var suffixLength = text.IndexOf(VersionSuffixEnd) - suffixStartIndex; + var suffixStartIndex = text.IndexOf(SuffixNumberStart) + SuffixNumberStart.Length; + var suffixLength = text.IndexOf(SuffixNumberEnd) - suffixStartIndex; suffix = text.Substring(suffixStartIndex, suffixLength); } - if (string.IsNullOrEmpty(suffix)) return prefix; + if (string.IsNullOrWhiteSpace(prefix) || !Version.TryParse(prefix, out _version)) + throw new Exception("The VersionPrefix in Version.targets is not a valid version number. I'm not sure what you're trying to do, but I'm not going to let you do it."); - else return prefix + "-" + suffix; + _versionPrefix = prefix; + if (string.IsNullOrWhiteSpace(suffix) || !int.TryParse(suffix, out _versionSuffix)) + throw new Exception("The SuffixNumber in Version.targets is not a number. I'm not sure what you're trying to do, but I'm not going to let you do it."); } - public static void SetCurrentVersionString(string prefix, string suffix = null) + public static void SetCurrentVersionString(string prefix, int suffix) { var text = File.ReadAllText(VersionTargetsPath); - var split = text.Split(new string[] { VersionSuffixStart, VersionSuffixEnd, VersionPrefixStart, VersionPrefixEnd }, StringSplitOptions.None); + var split = text.Split(new string[] { VersionSuffixStart, VersionSuffixEnd, SuffixNumberStart, SuffixNumberEnd, VersionPrefixStart, VersionPrefixEnd }, StringSplitOptions.None); - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendLine(split[0].TrimEnd()); sb.AppendLine(" " + VersionPrefixStart + prefix + VersionPrefixEnd); - if (!string.IsNullOrEmpty(suffix)) - { - sb.AppendLine(" " + VersionSuffixStart + suffix + VersionSuffixEnd); - } - sb.Append(" " + split[split.Length - 1].TrimStart()); + sb.AppendLine(" " + SuffixNumberStart + suffix + SuffixNumberEnd); + if (suffix > 0) + sb.AppendLine(" " + VersionSuffixStart + "pre.$(SuffixNumber)" + VersionSuffixEnd); + + sb.Append(" " + split[^1].TrimStart()); var final = sb.ToString(); diff --git a/Version.targets b/Version.targets index 9e43a2da..69107f7f 100644 --- a/Version.targets +++ b/Version.targets @@ -3,5 +3,7 @@ 1.0.0 + 23 + pre.$(SuffixNumber) \ No newline at end of file From 0d038fd6b62abf599c9f1169b28d11a93c1b732c Mon Sep 17 00:00:00 2001 From: Govorunb Date: Sat, 2 Dec 2023 11:29:44 +1100 Subject: [PATCH 5/8] feat: Allow nullables and params arrays in console commands (#505) * feat: Allow nullables and params arrays in console commands * fix: Forgot a newline Clarify parameter parsing error message --- Nautilus/Commands/ConsoleCommand.cs | 107 +++++++++++++------- Nautilus/Commands/Parameter.cs | 46 +++++++-- Nautilus/Extensions/GeneralExtensions.cs | 16 +++ Nautilus/Extensions/TypeExtensions.cs | 85 ++++++++++++++++ Nautilus/Patchers/ConsoleCommandsPatcher.cs | 101 ++++++++++++------ 5 files changed, 275 insertions(+), 80 deletions(-) create mode 100644 Nautilus/Extensions/TypeExtensions.cs diff --git a/Nautilus/Commands/ConsoleCommand.cs b/Nautilus/Commands/ConsoleCommand.cs index 6955feb7..66c24ce2 100644 --- a/Nautilus/Commands/ConsoleCommand.cs +++ b/Nautilus/Commands/ConsoleCommand.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Reflection; using HarmonyLib; +using Nautilus.Extensions; namespace Nautilus.Commands; @@ -24,7 +25,11 @@ internal class ConsoleCommand /// /// The parameters for the command. /// - public IEnumerable Parameters { get; } + public IReadOnlyList Parameters { get; } + /// + /// The minimum number of parameters required to invoke the command. + /// + public int RequiredParameterCount { get; } /// /// The types of the parameters. @@ -53,8 +58,9 @@ public ConsoleCommand(string trigger, MethodInfo targetMethod, bool isDelegate = IsDelegate = isDelegate; Instance = instance; ModName = DeclaringType.Assembly.GetName().Name; - Parameters = targetMethod.GetParameters().Select(param => new Parameter(param)); + Parameters = targetMethod.GetParameters().Select(param => new Parameter(param)).ToList(); ParameterTypes = Parameters.Select(param => param.ParameterType).ToArray(); + RequiredParameterCount = Parameters.Count(param => !param.IsOptional); } /// @@ -66,73 +72,96 @@ public bool HasValidInvoke() return IsDelegate || Instance != null || IsMethodStatic; } - /// - /// Determines whether the target methods parameters are valid. - /// - /// - public bool HasValidParameterTypes() - { - foreach (Parameter parameter in Parameters) - { - if (!parameter.IsValidParameterType) - { - return false; - } - } - - return true; - } - /// /// Returns a list of all invalid parameters. /// /// public IEnumerable GetInvalidParameters() { - return Parameters.Where(param => !param.IsValidParameterType); + return Parameters.Where(p => p.ValidState != Parameter.ValidationError.Valid); } /// /// Attempts to parse input parameters into appropriate types as defined in the target method. /// - /// The parameters as input by the user. + /// The parameters as input by the user. /// The parameters that have been successfully parsed. - /// Whether or not all parameters were succesfully parsed. - public bool TryParseParameters(IEnumerable inputParameters, out object[] parsedParameters) + /// + /// A tuple containing: + /// + /// The number of input items consumed. + /// The number of command parameters that were successfully parsed. + /// + /// + public (int consumed, int parsed) TryParseParameters(IReadOnlyList input, out object[] parsedParameters) { parsedParameters = null; // Detect incorrect number of parameters (allow for optional) - if (Parameters.Count() < inputParameters.Count() || - Parameters.Where(param => !param.IsOptional).Count() > inputParameters.Count()) + int paramCount = Parameters.Count; + int inputCount = input.Count; + int paramsArrayLength = Math.Max(0, input.Count - (paramCount - 1)); + + if (inputCount < RequiredParameterCount) { - return false; + return default; } - parsedParameters = new object[Parameters.Count()]; - for (int i = 0; i < Parameters.Count(); i++) + parsedParameters = new object[paramCount]; + for (int i = 0; i < paramCount; i++) { - Parameter parameter = Parameters.ElementAt(i); - - if (i >= inputParameters.Count()) // It's an optional parameter that wasn't passed by the user - { - parsedParameters[i] = Type.Missing; - continue; - } + Type paramType = Parameters[i].ParameterType; + parsedParameters[i] = paramType.TryUnwrapArrayType(out Type elementType) + ? Array.CreateInstance(elementType, paramsArrayLength) + : DBNull.Value; + } - string input = inputParameters.ElementAt(i); + int consumed = 0; + int parsed = 0; + while (consumed < inputCount) + { + if (parsed >= paramCount) break; + + Parameter parameter = Parameters[parsed]; + string inputItem = input[consumed]; + object parsedItem; try { - parsedParameters[i] = parameter.Parse(input); + parsedItem = parameter.Parse(inputItem); } catch (Exception) { - return false; // couldn't parse, wasn't a valid conversion + return (consumed, parsed); + } + consumed++; + + if (parameter.ParameterType.IsArray) + { + Array parsedArr = (Array)parsedParameters[parsed]; + parsedArr.SetValue(parsedItem, consumed - parsed - 1); + if (consumed >= inputCount) + { + parsed++; + } + } + else + { + parsedParameters[parsed] = parsedItem; + parsed++; } } - return true; + // Optional parameters that weren't passed by the user + // at this point all required parameters should've been parsed + for (int i = parsed; i < paramCount; i++) + { + if (parsedParameters[i] == DBNull.Value) + parsedParameters[i] = Type.Missing; + parsed++; + } + + return (consumed, parsed); } /// diff --git a/Nautilus/Commands/Parameter.cs b/Nautilus/Commands/Parameter.cs index c24ee012..f9aa3f3c 100644 --- a/Nautilus/Commands/Parameter.cs +++ b/Nautilus/Commands/Parameter.cs @@ -1,15 +1,21 @@ - using System; using System.Collections.Generic; using System.Globalization; -using System.Linq; using System.Reflection; +using Nautilus.Extensions; namespace Nautilus.Commands; internal struct Parameter { - private static Dictionary> TypeConverters = new() + [Flags] + public enum ValidationError + { + Valid = 0, + UnsupportedType = 1, + ArrayNotParams = 2, + } + private static Dictionary> _typeConverters = new() { [typeof(string)] = (s) => s, [typeof(bool)] = (s) => bool.Parse(s), @@ -18,23 +24,47 @@ internal struct Parameter [typeof(double)] = (s) => double.Parse(s, CultureInfo.InvariantCulture.NumberFormat) }; - public static IEnumerable SupportedTypes => TypeConverters.Keys; + public static IEnumerable SupportedTypes => _typeConverters.Keys; public Type ParameterType { get; } + public Type UnderlyingValueType { get; } public bool IsOptional { get; } public string Name { get; } - public bool IsValidParameterType { get; } + public ValidationError ValidState { get; } public Parameter(ParameterInfo parameter) { ParameterType = parameter.ParameterType; - IsOptional = parameter.IsOptional; + UnderlyingValueType = ParameterType.GetUnderlyingType(); + IsOptional = parameter.IsOptional || ParameterType.IsArray; Name = parameter.Name; - IsValidParameterType = SupportedTypes.Contains(ParameterType); + ValidState = ValidateParameter(parameter); + } + + private readonly ValidationError ValidateParameter(ParameterInfo paramInfo) + { + ValidationError valid = ValidationError.Valid; + // arrays MUST be a "params T[]" parameter + // this enforces them being last *and* only having one + if (ParameterType.IsArray && !paramInfo.IsDefined(typeof(ParamArrayAttribute), false)) + valid |= ValidationError.ArrayNotParams; + if (!_typeConverters.ContainsKey(UnderlyingValueType)) + valid |= ValidationError.UnsupportedType; + + return valid; } public object Parse(string input) { - return TypeConverters[ParameterType](input); + Type paramType = ParameterType; + if (paramType.TryUnwrapArrayType(out Type elementType)) + paramType = elementType; + if (paramType.TryUnwrapNullableType(out _)) + { + if (string.Equals(input, "null", StringComparison.OrdinalIgnoreCase)) + return null; + } + + return _typeConverters[UnderlyingValueType](input); } } \ No newline at end of file diff --git a/Nautilus/Extensions/GeneralExtensions.cs b/Nautilus/Extensions/GeneralExtensions.cs index b85bfe9f..819f52d6 100644 --- a/Nautilus/Extensions/GeneralExtensions.cs +++ b/Nautilus/Extensions/GeneralExtensions.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Text; using UnityEngine; namespace Nautilus.Extensions; @@ -43,4 +45,18 @@ public static void AddHint(this ErrorMessage @this, string message) else if (msg.timeEnd <= Time.time + @this.timeFadeOut) msg.timeEnd += @this.timeFadeOut + @this.timeInvisible; } + + /// + /// Concatenates string representations of the provided , + /// using the specified between them. + /// + /// Type of value that will be converted to . + /// The . + /// The to insert between each pair of values. + /// Values to concatenate into the . + /// The provided . + public static StringBuilder AppendJoin(this StringBuilder builder, string separator, IEnumerable values) + { + return builder.Append(string.Join(separator, values)); + } } \ No newline at end of file diff --git a/Nautilus/Extensions/TypeExtensions.cs b/Nautilus/Extensions/TypeExtensions.cs new file mode 100644 index 00000000..87536ae3 --- /dev/null +++ b/Nautilus/Extensions/TypeExtensions.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using HarmonyLib; + +namespace Nautilus.Extensions; + +internal static class TypeExtensions +{ + private static readonly List _builtinTypeAliases = new() + { + "void", + null, // all other types + "DBNull", + "bool", + "char", + "sbyte", + "byte", + "short", + "ushort", + "int", + "uint", + "long", + "ulong", + "float", + "double", + "decimal", + null, // DateTime? + null, // ??? + "string" + }; + + /// + /// Format the given 's name into a more developer-friendly form. + /// + /// + /// + public static string GetFriendlyName(this Type type) + { + if (type.TryUnwrapArrayType(out Type elementType)) + return GetFriendlyName(elementType) + "[]"; + + if (type.TryUnwrapNullableType(out Type valueType)) + return GetFriendlyName(valueType) + "?"; + + // TODO: format tuples as well + + if (type.IsConstructedGenericType) + return type.Name[..type.Name.LastIndexOf('`')] + + $"<{type.GenericTypeArguments.Select(GetFriendlyName).Join()}>"; + + return _builtinTypeAliases[(int) Type.GetTypeCode(type)] ?? type.Name; + } + + /// + /// "Unwraps" the inner from an array and/or nullable type. + /// + /// + /// + /// The inner type - for example, from a string[], or from bool?.
+ /// If the isn't wrapped, it is returned as-is. + ///
+ public static Type GetUnderlyingType(this Type type) + { + if (type.TryUnwrapArrayType(out Type elementType)) + type = elementType; + if (type.TryUnwrapNullableType(out Type valueType)) + type = valueType; + return type; + } + + public static bool TryUnwrapArrayType(this Type type, out Type elementType) + { + // GetElementType checks if it's an array, pointer, or reference + elementType = type.GetElementType(); + return type.IsArray // restrict to arrays only + && elementType != null; + } + + public static bool TryUnwrapNullableType(this Type type, out Type valueType) + { + valueType = Nullable.GetUnderlyingType(type); + return valueType != null; + } +} diff --git a/Nautilus/Patchers/ConsoleCommandsPatcher.cs b/Nautilus/Patchers/ConsoleCommandsPatcher.cs index 197488d9..12a08dd5 100644 --- a/Nautilus/Patchers/ConsoleCommandsPatcher.cs +++ b/Nautilus/Patchers/ConsoleCommandsPatcher.cs @@ -1,11 +1,13 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Reflection; +using System.Text; using System.Text.RegularExpressions; using BepInEx.Logging; using HarmonyLib; using Nautilus.Commands; +using Nautilus.Extensions; using Nautilus.Utility; using UnityEngine; @@ -13,7 +15,7 @@ namespace Nautilus.Patchers; internal static class ConsoleCommandsPatcher { - private static Dictionary ConsoleCommands = new(); + private static Dictionary ConsoleCommands = new(StringComparer.OrdinalIgnoreCase); private static Color CommandColor = new(1, 1, 0); private static Color ParameterTypeColor = new(0, 1, 1); @@ -63,17 +65,41 @@ public static void AddCustomCommand(string command, MethodInfo targetMethod, boo return; } - // if any of the parameter types of the method are unsupported, print an error and don't add it - if (!consoleCommand.HasValidParameterTypes()) + // if any of the parameters of the method aren't valid, print an error and don't add it + if (consoleCommand.GetInvalidParameters().Any()) { - string error = $"Could not register custom command {GetColoredString(consoleCommand)} for mod " + - $"{GetColoredString(consoleCommand.ModName, ModOriginColor)}\n" + - "The following parameters have unsupported types:\n" + - consoleCommand.GetInvalidParameters().Select(param => GetColoredString(param)).Join(delimiter: "\n") + - "Supported parameter types:\n" + - Parameter.SupportedTypes.Select(type => type.Name).Join(); + List parametersWithUnsupportedTypes = new(); + List nonParamsArrayParameters = new(); + foreach (var parameter in consoleCommand.GetInvalidParameters()) + { + Parameter.ValidationError state = parameter.ValidState; + if (state.HasFlag(Parameter.ValidationError.UnsupportedType)) + parametersWithUnsupportedTypes.Add(parameter); + if (state.HasFlag(Parameter.ValidationError.ArrayNotParams)) + nonParamsArrayParameters.Add(parameter); + } + + StringBuilder error = new StringBuilder( + $"Could not register custom command {GetColoredString(consoleCommand)} for mod " + + $"{GetColoredString(consoleCommand.ModName, ModOriginColor)}\n" + ); - LogAndAnnounce(error, LogLevel.Error); + if (parametersWithUnsupportedTypes.Count > 0) + { + error.AppendLine("The following parameters have unsupported types:"); + error.AppendJoin("\n", parametersWithUnsupportedTypes.Select(GetColoredString)); + error.AppendLine("\nSupported parameter types:"); + error.AppendJoin(",", Parameter.SupportedTypes.Select(type => type.GetFriendlyName())); + } + + if (nonParamsArrayParameters.Count > 0) + { + error.AppendLine("Array parameters must be marked as 'params'."); + error.AppendLine("Incorrect parameters:"); + error.AppendJoin(",", nonParamsArrayParameters.Select(GetColoredString)); + } + + LogAndAnnounce(error.ToString(), LogLevel.Error); return; } @@ -148,7 +174,7 @@ private static bool HandleCommand(string input) input = input.Trim(); string[] components = input.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); - string trigger = components[0].ToLowerInvariant(); + string trigger = components[0]; if (!ConsoleCommands.TryGetValue(trigger, out ConsoleCommand command)) { @@ -156,30 +182,39 @@ private static bool HandleCommand(string input) return false; } - IEnumerable parameters = components.Skip(1); + List inputParameters = components.Skip(1).ToList(); + + (int consumed, int parsed) = command.TryParseParameters(inputParameters, out object[] parsedParameters); // If the parameters couldn't be parsed by the command, print a user and developer-friendly error message both // on-screen and in the log. - if (!command.TryParseParameters(parameters, out object[] parsedParameters)) + bool consumedAll = consumed >= inputParameters.Count; + bool parsedAll = parsed == command.Parameters.Count; + if (!consumedAll || !parsedAll) { - if (parsedParameters != null) + if (!parsedAll) { - // Find the first invalid parameter - string invalidParameter = null; - string parameterTypeName = null; - for (int i = 0; i < parsedParameters.Length; i++) + if (parsedParameters != null) { - if (parsedParameters[i] == null) - { - invalidParameter = parameters.ElementAt(i); - parameterTypeName = command.ParameterTypes[i].Name; - break; - } - } + // Get the first invalid parameter + string invalidInput = inputParameters[consumed]; + + var invalidParameter = command.Parameters[parsed]; + string parameterTypeName = invalidParameter.UnderlyingValueType.GetFriendlyName(); - // Print a message about why it is invalid - string error = $"{GetColoredString(invalidParameter, ParameterInputColor)} is not a valid " + - $"{GetColoredString(parameterTypeName, ParameterTypeColor)}!"; + // Print a message about why it is invalid + string error = $"Parameter {GetColoredString(invalidParameter.Name, ParameterOptionalColor)} could not be parsed:\n" + + $"{GetColoredString(invalidInput, ParameterInputColor)} is not a valid " + + $"{GetColoredString(parameterTypeName, ParameterTypeColor)}!"; + + LogAndAnnounce(error, LogLevel.Error); + } + } + else if (!consumedAll) + { + string error = "Received too many parameters!\n" + + $"expected {GetColoredString(command.Parameters.Count.ToString(), ParameterTypeColor)} " + + $"but got {GetColoredString(inputParameters.Count.ToString(), ParameterInputColor)}"; LogAndAnnounce(error, LogLevel.Error); } @@ -187,14 +222,14 @@ private static bool HandleCommand(string input) // Print a message about what parameters the command expects string parameterInfoString = $"{GetColoredString(command.Trigger, CommandColor)} " + "expects the following parameters\n" + - command.Parameters.Select(param => GetColoredString(param)).Join(delimiter: "\n"); + command.Parameters.Select(GetColoredString).Join(delimiter: "\n"); LogAndAnnounce(parameterInfoString, LogLevel.Error); // Print a message detailing all received parameters. - if (parameters.Any()) + if (inputParameters.Any()) { - InternalLogger.Announce($"Received parameters: {parameters.Join()}", LogLevel.Error, true); + InternalLogger.Announce($"Received parameters: {inputParameters.Join()}", LogLevel.Error, true); } return true; // We've handled the command insofar as we've handled and reported the user error to them. @@ -232,7 +267,7 @@ private static string GetColoredString(ConsoleCommand command) private static string GetColoredString(Parameter parameter) { - return $"{parameter.Name}: {GetColoredString(parameter.ParameterType.Name, ParameterTypeColor)}" + + return $"{parameter.Name}: {GetColoredString(parameter.ParameterType.GetFriendlyName(), ParameterTypeColor)}" + (parameter.IsOptional ? $" {GetColoredString("(optional)", ParameterOptionalColor)}" : string.Empty); } From 75d926fc5ec03debcfdbed346c3251596781a3bc Mon Sep 17 00:00:00 2001 From: Metious <71298690+Metious@users.noreply.github.com> Date: Sat, 2 Dec 2023 04:03:56 +0330 Subject: [PATCH 6/8] fix: Loot distribution dependency on the prefab database (#501) Fixed loot distribution dependency on the database --- Nautilus/Handlers/LootDistributionHandler.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Nautilus/Handlers/LootDistributionHandler.cs b/Nautilus/Handlers/LootDistributionHandler.cs index 59087292..00f180b7 100644 --- a/Nautilus/Handlers/LootDistributionHandler.cs +++ b/Nautilus/Handlers/LootDistributionHandler.cs @@ -95,6 +95,8 @@ public static void AddLootDistributionData(string classId, LootDistributionData. /// The dictating how the prefab should spawn in the world. public static void AddLootDistributionData(string classId, params LootDistributionData.BiomeData[] biomeDistribution) { + CraftData.PreparePrefabIDCache(); + if (!PrefabDatabase.TryGetPrefabFilename(classId, out var filename)) { InternalLogger.Error($"Could not find prefab file path for class ID '{classId}'. Cancelling loot distribution addition."); @@ -112,6 +114,8 @@ public static void AddLootDistributionData(string classId, params LootDistributi /// The dictating how the prefab should spawn in the world. public static void AddLootDistributionData(string classId, WorldEntityInfo info, params LootDistributionData.BiomeData[] biomeDistribution) { + CraftData.PreparePrefabIDCache(); + if (!PrefabDatabase.TryGetPrefabFilename(classId, out var filename)) { InternalLogger.Error($"Could not find prefab file path for class ID '{classId}'. Cancelling loot distribution addition."); From 8f266ca7448597fe9dcb902c69cc28f21243b301 Mon Sep 17 00:00:00 2001 From: Metious <71298690+Metious@users.noreply.github.com> Date: Sat, 2 Dec 2023 23:03:22 +0330 Subject: [PATCH 7/8] fix: Fixed issue when yield returning same request (#498) * Fixed issue when yield returning same request The issue occurs because when you yield return the same request multiple times, the state machine advances but it will not wait until the code is completely executed. * Fixed missing reference when a prefab unloads * Better access modifiers --- Nautilus/Assets/ModPrefabCache.cs | 2 +- Nautilus/Assets/ModPrefabRequest.cs | 19 +++++++++++++++---- Nautilus/Patchers/PrefabDatabasePatcher.cs | 7 +++++++ 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/Nautilus/Assets/ModPrefabCache.cs b/Nautilus/Assets/ModPrefabCache.cs index ef74e5a8..933c546d 100644 --- a/Nautilus/Assets/ModPrefabCache.cs +++ b/Nautilus/Assets/ModPrefabCache.cs @@ -111,7 +111,7 @@ public void EnterPrefabIntoCache(GameObject prefab) if(!Entries.ContainsKey(prefabIdentifier.classId)) { Entries.Add(prefabIdentifier.classId, prefab); - InternalLogger.Debug($"ModPrefabCache: adding prefab {prefab}"); + InternalLogger.Debug($"ModPrefabCache: added prefab {prefab}"); } else // this should never happen { diff --git a/Nautilus/Assets/ModPrefabRequest.cs b/Nautilus/Assets/ModPrefabRequest.cs index dc5e67ed..c3154ca5 100644 --- a/Nautilus/Assets/ModPrefabRequest.cs +++ b/Nautilus/Assets/ModPrefabRequest.cs @@ -7,12 +7,14 @@ namespace Nautilus.Assets; // request for getting ModPrefab asynchronously -internal class ModPrefabRequest: IPrefabRequest, IEnumerator +internal class ModPrefabRequest: IPrefabRequest { + internal bool Done { get; private set; } + private readonly PrefabInfo prefabInfo; - - private int state = 0; + private CoroutineTask task; + private TaskResult taskResult; public ModPrefabRequest(PrefabInfo prefabInfo) @@ -50,13 +52,22 @@ public object Current public bool TryGetPrefab(out GameObject result) { result = taskResult.Get(); + if (!Done) + { + Done = result; + } return result != null; } public bool MoveNext() { Init(); - return state++ == 0; + if (task == null) + { + return false; + } + + return !TryGetPrefab(out _); } public void Reset() {} diff --git a/Nautilus/Patchers/PrefabDatabasePatcher.cs b/Nautilus/Patchers/PrefabDatabasePatcher.cs index 8ea415bc..172f2251 100644 --- a/Nautilus/Patchers/PrefabDatabasePatcher.cs +++ b/Nautilus/Patchers/PrefabDatabasePatcher.cs @@ -80,7 +80,14 @@ private static IPrefabRequest GetModPrefabAsync(string classId) } if(ModPrefabCache.Requests.TryGetValue(prefabInfo.ClassID, out var request)) + { + if (request.Done && !request.TryGetPrefab(out _)) + { + return new ModPrefabRequest(prefabInfo); + } + return request; + } return new ModPrefabRequest(prefabInfo); } From ef0a459b91cc8526b87e07758d8b229aafb75364 Mon Sep 17 00:00:00 2001 From: Metious <71298690+Metious@users.noreply.github.com> Date: Sat, 2 Dec 2023 23:05:29 +0330 Subject: [PATCH 8/8] fix: Fixed ambiguous method error for WithAnalysisTech (#499) Fixed ambiguous method error for AnalysisTech --- Nautilus/Assets/Gadgets/ScanningGadget.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Nautilus/Assets/Gadgets/ScanningGadget.cs b/Nautilus/Assets/Gadgets/ScanningGadget.cs index a84dec1e..367a66ad 100644 --- a/Nautilus/Assets/Gadgets/ScanningGadget.cs +++ b/Nautilus/Assets/Gadgets/ScanningGadget.cs @@ -318,7 +318,7 @@ public ScanningGadget WithAnalysisTech( /// A reference to this instance after the operation has completed. public ScanningGadget WithAnalysisTech( Sprite popupSprite, - List storyGoalsToTrigger = null, + List storyGoalsToTrigger, FMODAsset unlockSound = null, string unlockMessage = null )