Partition quest loading into different methods
authorLiza Carvelli <liza@carvel.li>
Thu, 25 Jul 2024 02:15:44 +0000 (04:15 +0200)
committerLiza Carvelli <liza@carvel.li>
Thu, 25 Jul 2024 02:15:44 +0000 (04:15 +0200)
QuestPathGenerator.Tests/QuestPathGenerator.Tests.csproj
QuestPathGenerator/QuestPathGenerator.csproj
QuestPathGenerator/QuestSourceGenerator.cs
QuestPaths/AssemblyQuestLoader.cs
QuestPaths/QuestPaths.csproj
Questionable.Model/Questionable.Model.csproj
Questionable.sln
Questionable/Controller/QuestController.cs
Questionable/Controller/QuestRegistry.cs
Questionable/Validation/QuestValidator.cs
Questionable/Windows/QuestSelectionWindow.cs

index 98a27c97c74dc1b2573b432dbd68685c999d401d..a6c43a4f9e62f6ffd4cebcd8afeb48306e554307 100644 (file)
@@ -7,13 +7,14 @@
 
         <IsPackable>false</IsPackable>
         <IsTestProject>true</IsTestProject>
+        <Platforms>x64</Platforms>
     </PropertyGroup>
 
     <ItemGroup>
-        <PackageReference Include="coverlet.collector" Version="6.0.0"/>
-        <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0"/>
-        <PackageReference Include="xunit" Version="2.5.3"/>
-        <PackageReference Include="xunit.runner.visualstudio" Version="2.5.3"/>
+        <PackageReference Include="coverlet.collector" Version="6.0.0" />
+        <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
+        <PackageReference Include="xunit" Version="2.5.3" />
+        <PackageReference Include="xunit.runner.visualstudio" Version="2.5.3" />
     </ItemGroup>
 
     <ItemGroup>
index 8ee14a8f25ff34fc03023f826485296b756aaa68..d9b119d4dd8f410e6b32c0b69eac704aae957781 100644 (file)
@@ -1,4 +1,4 @@
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
     <PropertyGroup>
         <TargetFramework>netstandard2.0</TargetFramework>
         <IsPackable>false</IsPackable>
@@ -13,6 +13,7 @@
 
         <PackageId>QuestPathGenerator</PackageId>
         <RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
+        <Platforms>x64</Platforms>
     </PropertyGroup>
 
     <ItemGroup>
@@ -23,8 +24,8 @@
             <PrivateAssets>all</PrivateAssets>
             <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
         </PackageReference>
-        <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.9.2"/>
-        <PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.9.2"/>
+        <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.9.2" />
+        <PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.9.2" />
         <PackageReference Include="System.Text.Json" Version="8.0.4" PrivateAssets="all" />
     </ItemGroup>
 
index 02fc2715fc851ab00387a23667237590b2d71e8d..2e2d75303c34a68076de8678a4964c487ae7295f 100644 (file)
@@ -92,7 +92,43 @@ public class QuestSourceGenerator : ISourceGenerator
         if (quests.Count == 0)
             return;
 
-        quests = quests.OrderBy(x => x.Item1).ToList();
+        var partitionedQuests = quests
+            .OrderBy(x => x.Item1)
+            .GroupBy(x => $"LoadQuests{x.Item1 / 50}")
+            .ToList();
+
+        List<MethodDeclarationSyntax> methods =
+        [
+            MethodDeclaration(
+                    PredefinedType(
+                        Token(SyntaxKind.VoidKeyword)),
+                    Identifier("LoadQuests"))
+                .WithModifiers(
+                    TokenList(
+                        Token(SyntaxKind.PrivateKeyword),
+                        Token(SyntaxKind.StaticKeyword)))
+                .WithBody(
+                    Block(
+                        partitionedQuests
+                            .Select(x =>
+                                ExpressionStatement(
+                                    InvocationExpression(
+                                        IdentifierName(x.Key))))))
+        ];
+
+        foreach (var partition in partitionedQuests)
+        {
+            methods.Add(MethodDeclaration(
+                    PredefinedType(
+                        Token(SyntaxKind.VoidKeyword)),
+                    Identifier(partition.Key))
+                .WithModifiers(
+                    TokenList(
+                        Token(SyntaxKind.PrivateKeyword),
+                        Token(SyntaxKind.StaticKeyword)))
+                .WithBody(
+                    Block(CreateInitializer(partition.ToList()))));
+        }
 
         var code =
             CompilationUnit()
@@ -132,116 +168,61 @@ public class QuestSourceGenerator : ISourceGenerator
                                 SingletonList<MemberDeclarationSyntax>(
                                     ClassDeclaration("AssemblyQuestLoader")
                                         .WithModifiers(
-                                            TokenList(
-                                            [
-                                                Token(SyntaxKind.PartialKeyword)
-                                            ]))
-                                        .WithMembers(
-                                            SingletonList<MemberDeclarationSyntax>(
-                                                FieldDeclaration(
-                                                        VariableDeclaration(
-                                                                GenericName(
-                                                                        Identifier("IReadOnlyDictionary"))
-                                                                    .WithTypeArgumentList(
-                                                                        TypeArgumentList(
-                                                                            SeparatedList<TypeSyntax>(
-                                                                                new SyntaxNodeOrToken[]
-                                                                                {
-                                                                                    PredefinedType(
-                                                                                        Token(SyntaxKind
-                                                                                            .UShortKeyword)),
-                                                                                    Token(SyntaxKind.CommaToken),
-                                                                                    IdentifierName("QuestRoot")
-                                                                                }))))
-                                                            .WithVariables(
-                                                                SingletonSeparatedList(
-                                                                    VariableDeclarator(
-                                                                            Identifier("Quests"))
-                                                                        .WithInitializer(
-                                                                            EqualsValueClause(
-                                                                                ObjectCreationExpression(
-                                                                                        GenericName(
-                                                                                                Identifier(
-                                                                                                    "Dictionary"))
-                                                                                            .WithTypeArgumentList(
-                                                                                                TypeArgumentList(
-                                                                                                    SeparatedList<
-                                                                                                        TypeSyntax>(
-                                                                                                        new
-                                                                                                            SyntaxNodeOrToken
-                                                                                                            []
-                                                                                                            {
-                                                                                                                PredefinedType(
-                                                                                                                    Token(
-                                                                                                                        SyntaxKind
-                                                                                                                            .UShortKeyword)),
-                                                                                                                Token(
-                                                                                                                    SyntaxKind
-                                                                                                                        .CommaToken),
-                                                                                                                IdentifierName(
-                                                                                                                    "QuestRoot")
-                                                                                                            }))))
-                                                                                    .WithArgumentList(
-                                                                                        ArgumentList())
-                                                                                    .WithInitializer(
-                                                                                        InitializerExpression(
-                                                                                            SyntaxKind
-                                                                                                .CollectionInitializerExpression,
-                                                                                            SeparatedList<
-                                                                                                ExpressionSyntax>(
-                                                                                                quests.SelectMany(x =>
-                                                                                                    CreateQuestInitializer(
-                                                                                                            x.Item1,
-                                                                                                            x.Item2)
-                                                                                                        .ToArray())))))))))
-                                                    .WithModifiers(
-                                                        TokenList(
-                                                        [
-                                                            Token(SyntaxKind.InternalKeyword),
-                                                            Token(SyntaxKind.StaticKeyword)
-                                                        ]))))))))
+                                            TokenList(Token(SyntaxKind.PartialKeyword)))
+                                        .WithMembers(List<MemberDeclarationSyntax>(methods))))))
                 .NormalizeWhitespace();
 
         // Add the source code to the compilation.
         context.AddSource("AssemblyQuestLoader.g.cs", code.ToFullString());
     }
 
-    private static IEnumerable<SyntaxNodeOrToken> CreateQuestInitializer(ushort questId, QuestRoot quest)
+    private static StatementSyntax[] CreateInitializer(List<(ushort QuestId, QuestRoot Root)> quests)
+    {
+        List<StatementSyntax> statements = [];
+
+        foreach (var quest in quests)
+        {
+            statements.Add(
+                ExpressionStatement(
+                    InvocationExpression(
+                            IdentifierName("AddQuest"))
+                        .WithArgumentList(
+                            ArgumentList(
+                                SeparatedList<ArgumentSyntax>(
+                                    new SyntaxNodeOrToken[]
+                                    {
+                                        Argument(
+                                            LiteralExpression(SyntaxKind.NumericLiteralExpression,
+                                                Literal(quest.QuestId))),
+                                        Token(SyntaxKind.CommaToken),
+                                        Argument(CreateQuestRootExpression(quest.QuestId, quest.Root))
+                                    })))));
+        }
+
+        return statements.ToArray();
+    }
+
+    private static ObjectCreationExpressionSyntax CreateQuestRootExpression(ushort questId, QuestRoot quest)
     {
         try
         {
-            return new SyntaxNodeOrToken[]
-            {
-                InitializerExpression(
-                    SyntaxKind.ComplexElementInitializerExpression,
-                    SeparatedList<ExpressionSyntax>(
-                        new SyntaxNodeOrToken[]
-                        {
-                            LiteralExpression(
-                                SyntaxKind.NumericLiteralExpression,
-                                Literal(questId)),
-                            Token(SyntaxKind.CommaToken),
-                            ObjectCreationExpression(
-                                    IdentifierName(nameof(QuestRoot)))
-                                .WithInitializer(
-                                    InitializerExpression(
-                                        SyntaxKind.ObjectInitializerExpression,
-                                        SeparatedList<ExpressionSyntax>(
-                                            SyntaxNodeList(
-                                                AssignmentList(nameof(QuestRoot.Author), quest.Author)
-                                                    .AsSyntaxNodeOrToken(),
-                                                Assignment(nameof(QuestRoot.Comment), quest.Comment, null)
-                                                    .AsSyntaxNodeOrToken(),
-                                                AssignmentList(nameof(QuestRoot.TerritoryBlacklist),
-                                                    quest.TerritoryBlacklist).AsSyntaxNodeOrToken(),
-                                                AssignmentExpression(
-                                                    SyntaxKind.SimpleAssignmentExpression,
-                                                    IdentifierName(nameof(QuestRoot.QuestSequence)),
-                                                    CreateQuestSequence(quest.QuestSequence))
-                                            ))))
-                        })),
-                Token(SyntaxKind.CommaToken)
-            };
+            return ObjectCreationExpression(
+                    IdentifierName(nameof(QuestRoot)))
+                .WithInitializer(
+                    InitializerExpression(
+                        SyntaxKind.ObjectInitializerExpression,
+                        SeparatedList<ExpressionSyntax>(
+                            SyntaxNodeList(
+                                AssignmentList(nameof(QuestRoot.Author), quest.Author)
+                                    .AsSyntaxNodeOrToken(),
+                                Assignment(nameof(QuestRoot.Comment), quest.Comment, null)
+                                    .AsSyntaxNodeOrToken(),
+                                AssignmentList(nameof(QuestRoot.TerritoryBlacklist),
+                                    quest.TerritoryBlacklist).AsSyntaxNodeOrToken(),
+                                AssignmentExpression(
+                                    SyntaxKind.SimpleAssignmentExpression,
+                                    IdentifierName(nameof(QuestRoot.QuestSequence)),
+                                    CreateQuestSequence(quest.QuestSequence))))));
         }
         catch (Exception e)
         {
index 086e4ad9b161c44ed168fb30d6c7d122a9a2dd6f..afc7ea83e807f0bfd39568a67460e0061a8c134c 100644 (file)
@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
 using System.Diagnostics.CodeAnalysis;
 using System.IO;
 using System.Reflection;
@@ -9,13 +10,23 @@ namespace Questionable.QuestPaths;
 [SuppressMessage("ReSharper", "PartialTypeWithSinglePart", Justification = "Required for RELEASE")]
 public static partial class AssemblyQuestLoader
 {
-    public static IReadOnlyDictionary<ushort, QuestRoot> GetQuests() =>
+    private static Dictionary<ushort, QuestRoot>? _quests;
+
+    public static IReadOnlyDictionary<ushort, QuestRoot> GetQuests()
+    {
+        if (_quests == null)
+        {
+            _quests = [];
 #if RELEASE
-        Quests;
-#else
-        new Dictionary<ushort, QuestRoot>();
+            LoadQuests();
 #endif
+        }
+
+        return _quests ?? throw new InvalidOperationException("quest data is not initialized");
+    }
 
     public static Stream QuestSchema =>
         typeof(AssemblyQuestLoader).Assembly.GetManifestResourceStream("Questionable.QuestPaths.QuestSchema")!;
+
+    private static void AddQuest(ushort questId, QuestRoot root) => _quests![questId] = root;
 }
index 6d9e7d785dbf9cead9e720af0ee1bb3fd88ea140..bb2b3663f9d92bb4a586b5f86b166ae22ee49c0c 100644 (file)
@@ -9,35 +9,34 @@
         <DebugType>none</DebugType>
         <PathMap Condition="$(SolutionDir) != ''">$(SolutionDir)=X:\</PathMap>
         <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
+        <Platforms>x64</Platforms>
     </PropertyGroup>
 
     <ItemGroup>
-        <ProjectReference Include="..\Questionable.Model\Questionable.Model.csproj"/>
-        <ProjectReference Include="..\QuestPathGenerator\QuestPathGenerator.csproj"
-                          OutputItemType="Analyzer"
-                          ReferenceOutputAssembly="false"/>
+        <ProjectReference Include="..\Questionable.Model\Questionable.Model.csproj" />
+        <ProjectReference Include="..\QuestPathGenerator\QuestPathGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
     </ItemGroup>
 
     <ItemGroup>
-        <None Remove="quest-v1.json"/>
+        <None Remove="quest-v1.json" />
         <EmbeddedResource Include="quest-v1.json">
             <LogicalName>Questionable.QuestPaths.QuestSchema</LogicalName>
         </EmbeddedResource>
-        <AdditionalFiles Include="quest-v1.json"/>
+        <AdditionalFiles Include="quest-v1.json" />
     </ItemGroup>
 
     <ItemGroup Condition="'$(Configuration)' == 'Release'">
-        <None Remove="2.x - A Realm Reborn"/>
-        <None Remove="3.x - Heavensward"/>
-        <None Remove="4.x - Stormblood"/>
-        <None Remove="5.x - Shadowbringers"/>
-        <None Remove="6.x - Endwalker"/>
-        <None Remove="7.x - Dawntrail"/>
-        <AdditionalFiles Include="2.x - A Realm Reborn\**\*.json"/>
-        <AdditionalFiles Include="3.x - Heavensward\**\*.json"/>
-        <AdditionalFiles Include="4.x - Stormblood\**\*.json"/>
-        <AdditionalFiles Include="5.x - Shadowbringers\**\*.json"/>
+        <None Remove="2.x - A Realm Reborn" />
+        <None Remove="3.x - Heavensward" />
+        <None Remove="4.x - Stormblood" />
+        <None Remove="5.x - Shadowbringers" />
+        <None Remove="6.x - Endwalker" />
+        <None Remove="7.x - Dawntrail" />
+        <AdditionalFiles Include="2.x - A Realm Reborn\**\*.json" />
+        <AdditionalFiles Include="3.x - Heavensward\**\*.json" />
+        <AdditionalFiles Include="4.x - Stormblood\**\*.json" />
+        <AdditionalFiles Include="5.x - Shadowbringers\**\*.json" />
         <AdditionalFiles Include="6.x - Endwalker\**\*.json" />
-        <AdditionalFiles Include="7.x - Dawntrail\**\*.json"/>
+        <AdditionalFiles Include="7.x - Dawntrail\**\*.json" />
     </ItemGroup>
 </Project>
index 8909f97e2136b39451a647037f7dd4d7f5223507..cb320ec55be7762ceaf8a5c1232dbcc190dcb865 100644 (file)
@@ -7,6 +7,7 @@
         <PathMap Condition="$(SolutionDir) != ''">$(SolutionDir)=X:\</PathMap>
         <RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
         <DebugType>portable</DebugType>
+        <Platforms>x64</Platforms>
     </PropertyGroup>
 
     <ItemGroup>
index 0e614b4100b7ba78ad0a5d3545633375e555e528..5dd7596434d3358aeed55e5e697375200b46d1a3 100644 (file)
@@ -1,46 +1,48 @@
 
 Microsoft Visual Studio Solution File, Format Version 12.00
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Questionable", "Questionable\Questionable.csproj", "{C91EEF13-A1AC-4A40-B695-DD4E378E5989}"
+# Visual Studio Version 17
+VisualStudioVersion = 17.10.35013.160
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Questionable", "Questionable\Questionable.csproj", "{C91EEF13-A1AC-4A40-B695-DD4E378E5989}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LLib", "LLib\LLib.csproj", "{EEDE3BBE-E260-445E-8FB3-1264E0CBBE91}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LLib", "LLib\LLib.csproj", "{EEDE3BBE-E260-445E-8FB3-1264E0CBBE91}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QuestPaths", "QuestPaths\QuestPaths.csproj", "{7A136F28-8D5C-478D-B993-0F39F1451A47}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "QuestPaths", "QuestPaths\QuestPaths.csproj", "{7A136F28-8D5C-478D-B993-0F39F1451A47}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QuestPaths", "QuestPathGenerator\QuestPathGenerator.csproj", "{DFFD56A8-FA89-4585-A47B-C6AB27B65F0F}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "QuestPathGenerator", "QuestPathGenerator\QuestPathGenerator.csproj", "{DFFD56A8-FA89-4585-A47B-C6AB27B65F0F}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Questionable.Model", "Questionable.Model\Questionable.Model.csproj", "{E15144A5-AFF5-4D86-9561-AFF7DF7F505D}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Questionable.Model", "Questionable.Model\Questionable.Model.csproj", "{E15144A5-AFF5-4D86-9561-AFF7DF7F505D}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QuestPathGenerator.Tests", "QuestPathGenerator.Tests\QuestPathGenerator.Tests.csproj", "{4FD6F346-8961-4BD5-BDA2-E5F426DE4FC7}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "QuestPathGenerator.Tests", "QuestPathGenerator.Tests\QuestPathGenerator.Tests.csproj", "{4FD6F346-8961-4BD5-BDA2-E5F426DE4FC7}"
 EndProject
 Global
        GlobalSection(SolutionConfigurationPlatforms) = preSolution
-               Debug|Any CPU = Debug|Any CPU
-               Release|Any CPU = Release|Any CPU
+               Debug|x64 = Debug|x64
+               Release|x64 = Release|x64
        EndGlobalSection
        GlobalSection(ProjectConfigurationPlatforms) = postSolution
-               {C91EEF13-A1AC-4A40-B695-DD4E378E5989}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-               {C91EEF13-A1AC-4A40-B695-DD4E378E5989}.Debug|Any CPU.Build.0 = Debug|Any CPU
-               {C91EEF13-A1AC-4A40-B695-DD4E378E5989}.Release|Any CPU.ActiveCfg = Release|Any CPU
-               {C91EEF13-A1AC-4A40-B695-DD4E378E5989}.Release|Any CPU.Build.0 = Release|Any CPU
-               {EEDE3BBE-E260-445E-8FB3-1264E0CBBE91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-               {EEDE3BBE-E260-445E-8FB3-1264E0CBBE91}.Debug|Any CPU.Build.0 = Debug|Any CPU
-               {EEDE3BBE-E260-445E-8FB3-1264E0CBBE91}.Release|Any CPU.ActiveCfg = Release|Any CPU
-               {EEDE3BBE-E260-445E-8FB3-1264E0CBBE91}.Release|Any CPU.Build.0 = Release|Any CPU
-               {7A136F28-8D5C-478D-B993-0F39F1451A47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-               {7A136F28-8D5C-478D-B993-0F39F1451A47}.Debug|Any CPU.Build.0 = Debug|Any CPU
-               {7A136F28-8D5C-478D-B993-0F39F1451A47}.Release|Any CPU.ActiveCfg = Release|Any CPU
-               {7A136F28-8D5C-478D-B993-0F39F1451A47}.Release|Any CPU.Build.0 = Release|Any CPU
-               {DFFD56A8-FA89-4585-A47B-C6AB27B65F0F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-               {DFFD56A8-FA89-4585-A47B-C6AB27B65F0F}.Debug|Any CPU.Build.0 = Debug|Any CPU
-               {DFFD56A8-FA89-4585-A47B-C6AB27B65F0F}.Release|Any CPU.ActiveCfg = Release|Any CPU
-               {DFFD56A8-FA89-4585-A47B-C6AB27B65F0F}.Release|Any CPU.Build.0 = Release|Any CPU
-               {E15144A5-AFF5-4D86-9561-AFF7DF7F505D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-               {E15144A5-AFF5-4D86-9561-AFF7DF7F505D}.Debug|Any CPU.Build.0 = Debug|Any CPU
-               {E15144A5-AFF5-4D86-9561-AFF7DF7F505D}.Release|Any CPU.ActiveCfg = Release|Any CPU
-               {E15144A5-AFF5-4D86-9561-AFF7DF7F505D}.Release|Any CPU.Build.0 = Release|Any CPU
-               {4FD6F346-8961-4BD5-BDA2-E5F426DE4FC7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-               {4FD6F346-8961-4BD5-BDA2-E5F426DE4FC7}.Debug|Any CPU.Build.0 = Debug|Any CPU
-               {4FD6F346-8961-4BD5-BDA2-E5F426DE4FC7}.Release|Any CPU.ActiveCfg = Release|Any CPU
-               {4FD6F346-8961-4BD5-BDA2-E5F426DE4FC7}.Release|Any CPU.Build.0 = Release|Any CPU
+               {C91EEF13-A1AC-4A40-B695-DD4E378E5989}.Debug|x64.ActiveCfg = ExportRelease|x64
+               {C91EEF13-A1AC-4A40-B695-DD4E378E5989}.Debug|x64.Build.0 = ExportRelease|x64
+               {EEDE3BBE-E260-445E-8FB3-1264E0CBBE91}.Debug|x64.ActiveCfg = ExportRelease|x64
+               {EEDE3BBE-E260-445E-8FB3-1264E0CBBE91}.Debug|x64.Build.0 = ExportRelease|x64
+               {7A136F28-8D5C-478D-B993-0F39F1451A47}.Debug|x64.ActiveCfg = Debug|x64
+               {7A136F28-8D5C-478D-B993-0F39F1451A47}.Debug|x64.Build.0 = Debug|x64
+               {7A136F28-8D5C-478D-B993-0F39F1451A47}.Release|x64.ActiveCfg = Release|x64
+               {7A136F28-8D5C-478D-B993-0F39F1451A47}.Release|x64.Build.0 = Release|x64
+               {DFFD56A8-FA89-4585-A47B-C6AB27B65F0F}.Debug|x64.ActiveCfg = Debug|x64
+               {DFFD56A8-FA89-4585-A47B-C6AB27B65F0F}.Debug|x64.Build.0 = Debug|x64
+               {DFFD56A8-FA89-4585-A47B-C6AB27B65F0F}.Release|x64.ActiveCfg = Release|x64
+               {DFFD56A8-FA89-4585-A47B-C6AB27B65F0F}.Release|x64.Build.0 = Release|x64
+               {E15144A5-AFF5-4D86-9561-AFF7DF7F505D}.Debug|x64.ActiveCfg = Debug|x64
+               {E15144A5-AFF5-4D86-9561-AFF7DF7F505D}.Debug|x64.Build.0 = Debug|x64
+               {E15144A5-AFF5-4D86-9561-AFF7DF7F505D}.Release|x64.ActiveCfg = Release|x64
+               {E15144A5-AFF5-4D86-9561-AFF7DF7F505D}.Release|x64.Build.0 = Release|x64
+               {4FD6F346-8961-4BD5-BDA2-E5F426DE4FC7}.Debug|x64.ActiveCfg = Debug|x64
+               {4FD6F346-8961-4BD5-BDA2-E5F426DE4FC7}.Debug|x64.Build.0 = Debug|x64
+               {4FD6F346-8961-4BD5-BDA2-E5F426DE4FC7}.Release|x64.ActiveCfg = Release|x64
+               {4FD6F346-8961-4BD5-BDA2-E5F426DE4FC7}.Release|x64.Build.0 = Release|x64
+       EndGlobalSection
+       GlobalSection(SolutionProperties) = preSolution
+               HideSolutionNode = FALSE
        EndGlobalSection
 EndGlobal
index b255a34ac6f4abf11f0341791d35bef395111d9e..62f3a9359530f28893aeb8dcaea782cf758f5e8b 100644 (file)
@@ -423,7 +423,6 @@ internal sealed class QuestController
             _logger.LogError(e, "Failed to update task {TaskName}", _currentTask.ToString());
             _chatGui.PrintError(
                 $"[Questionable] Failed to update task '{_currentTask}', please check /xllog for details.");
-            Stop("Task failed to start");
             Stop("Task failed to update");
             return;
         }
index a7b83b7f54cf482d19ae84d7fee54bdde3b7fd66..a584e776c320cd662985b9fefe70d9fe6c8528a1 100644 (file)
@@ -63,7 +63,7 @@ internal sealed class QuestRegistry
         }
 
         ValidateQuests();
-        _logger.LogInformation("Loaded {Count} quests", _quests.Count);
+        _logger.LogInformation("Loaded {Count} quests in total", _quests.Count);
     }
 
     [Conditional("RELEASE")]
@@ -82,6 +82,8 @@ internal sealed class QuestRegistry
             };
             _quests[questId] = quest;
         }
+
+        _logger.LogInformation("Loaded {Count} quests from assembly", _quests.Count);
     }
 
     [Conditional("DEBUG")]
index b5b7bd4f66df6068ff0610e7bcf1d9c62e35c707..d53a5b52c601434d208abfb703acfcb90decaa36 100644 (file)
@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
 using System.Linq;
 using System.Threading;
 using System.Threading.Tasks;
@@ -38,26 +39,35 @@ internal sealed class QuestValidator
     {
         Task.Factory.StartNew(() =>
         {
-            foreach (var quest in quests)
+            try
             {
-                foreach (var validator in _validators)
+                foreach (var quest in quests)
                 {
-                    foreach (var issue in validator.Validate(quest))
+                    foreach (var validator in _validators)
                     {
-                        var level = issue.Severity == EIssueSeverity.Error ? LogLevel.Warning : LogLevel.Information;
-                        _logger.Log(level,
-                            "Validation failed: {QuestId} ({QuestName}) / {QuestSequence} / {QuestStep} - {Description}",
-                            issue.QuestId, quest.Info.Name, issue.Sequence, issue.Step, issue.Description);
-                        _validationIssues.Add(issue);
+                        foreach (var issue in validator.Validate(quest))
+                        {
+                            var level = issue.Severity == EIssueSeverity.Error
+                                ? LogLevel.Warning
+                                : LogLevel.Information;
+                            _logger.Log(level,
+                                "Validation failed: {QuestId} ({QuestName}) / {QuestSequence} / {QuestStep} - {Description}",
+                                issue.QuestId, quest.Info.Name, issue.Sequence, issue.Step, issue.Description);
+                            _validationIssues.Add(issue);
+                        }
                     }
                 }
-            }
 
-            _validationIssues = _validationIssues.OrderBy(x => x.QuestId)
-                .ThenBy(x => x.Sequence)
-                .ThenBy(x => x.Step)
-                .ThenBy(x => x.Description)
-                .ToList();
+                _validationIssues = _validationIssues.OrderBy(x => x.QuestId)
+                    .ThenBy(x => x.Sequence)
+                    .ThenBy(x => x.Step)
+                    .ThenBy(x => x.Description)
+                    .ToList();
+            }
+            catch (Exception e)
+            {
+                _logger.LogError(e, "Unable to validate quests");
+            }
         }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default);
     }
 }
index 9d48d69a9c6d320e230719469a5a146eca2777a1..592e2b82c178031e965d45b659dd98d49236295a 100644 (file)
@@ -228,10 +228,10 @@ internal sealed class QuestSelectionWindow : LWindow
                 ImGui.SameLine();
 
                 if (knownQuest != null &&
-                    knownQuest.FindSequence(0)?.LastStep()?.InteractionType == EInteractionType.AcceptQuest /* &&
+                    knownQuest.FindSequence(0)?.LastStep()?.InteractionType == EInteractionType.AcceptQuest &&
                     !_gameFunctions.IsQuestAccepted(quest.QuestId) &&
                     !_gameFunctions.IsQuestLocked(quest.QuestId) &&
-                    (quest.IsRepeatable || !_gameFunctions.IsQuestAcceptedOrComplete(quest.QuestId))*/)
+                    (quest.IsRepeatable || !_gameFunctions.IsQuestAcceptedOrComplete(quest.QuestId)))
                 {
                     ImGui.BeginDisabled(_questController.NextQuest != null || _questController.SimulatedQuest != null);