Partition quest loading into different methods

hw-p2
Liza 2024-07-25 04:15:44 +02:00
parent b5589b0054
commit 042a8b5ecc
Signed by: liza
GPG Key ID: 7199F8D727D55F67
11 changed files with 189 additions and 182 deletions

View File

@ -7,13 +7,14 @@
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject> <IsTestProject>true</IsTestProject>
<Platforms>x64</Platforms>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0"/> <PackageReference Include="coverlet.collector" Version="6.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0"/> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="xunit" Version="2.5.3"/> <PackageReference Include="xunit" Version="2.5.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3"/> <PackageReference Include="xunit.runner.visualstudio" Version="2.5.3" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
@ -13,6 +13,7 @@
<PackageId>QuestPathGenerator</PackageId> <PackageId>QuestPathGenerator</PackageId>
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile> <RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
<Platforms>x64</Platforms>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@ -23,8 +24,8 @@
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" 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="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.9.2" />
<PackageReference Include="System.Text.Json" Version="8.0.4" PrivateAssets="all" /> <PackageReference Include="System.Text.Json" Version="8.0.4" PrivateAssets="all" />
</ItemGroup> </ItemGroup>

View File

@ -92,7 +92,43 @@ public class QuestSourceGenerator : ISourceGenerator
if (quests.Count == 0) if (quests.Count == 0)
return; 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 = var code =
CompilationUnit() CompilationUnit()
@ -132,116 +168,61 @@ public class QuestSourceGenerator : ISourceGenerator
SingletonList<MemberDeclarationSyntax>( SingletonList<MemberDeclarationSyntax>(
ClassDeclaration("AssemblyQuestLoader") ClassDeclaration("AssemblyQuestLoader")
.WithModifiers( .WithModifiers(
TokenList( TokenList(Token(SyntaxKind.PartialKeyword)))
[ .WithMembers(List<MemberDeclarationSyntax>(methods))))))
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)
]))))))))
.NormalizeWhitespace(); .NormalizeWhitespace();
// Add the source code to the compilation. // Add the source code to the compilation.
context.AddSource("AssemblyQuestLoader.g.cs", code.ToFullString()); 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 try
{ {
return new SyntaxNodeOrToken[] return ObjectCreationExpression(
{ IdentifierName(nameof(QuestRoot)))
InitializerExpression( .WithInitializer(
SyntaxKind.ComplexElementInitializerExpression, InitializerExpression(
SeparatedList<ExpressionSyntax>( SyntaxKind.ObjectInitializerExpression,
new SyntaxNodeOrToken[] SeparatedList<ExpressionSyntax>(
{ SyntaxNodeList(
LiteralExpression( AssignmentList(nameof(QuestRoot.Author), quest.Author)
SyntaxKind.NumericLiteralExpression, .AsSyntaxNodeOrToken(),
Literal(questId)), Assignment(nameof(QuestRoot.Comment), quest.Comment, null)
Token(SyntaxKind.CommaToken), .AsSyntaxNodeOrToken(),
ObjectCreationExpression( AssignmentList(nameof(QuestRoot.TerritoryBlacklist),
IdentifierName(nameof(QuestRoot))) quest.TerritoryBlacklist).AsSyntaxNodeOrToken(),
.WithInitializer( AssignmentExpression(
InitializerExpression( SyntaxKind.SimpleAssignmentExpression,
SyntaxKind.ObjectInitializerExpression, IdentifierName(nameof(QuestRoot.QuestSequence)),
SeparatedList<ExpressionSyntax>( CreateQuestSequence(quest.QuestSequence))))));
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)
};
} }
catch (Exception e) catch (Exception e)
{ {

View File

@ -1,4 +1,5 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
@ -9,13 +10,23 @@ namespace Questionable.QuestPaths;
[SuppressMessage("ReSharper", "PartialTypeWithSinglePart", Justification = "Required for RELEASE")] [SuppressMessage("ReSharper", "PartialTypeWithSinglePart", Justification = "Required for RELEASE")]
public static partial class AssemblyQuestLoader 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 #if RELEASE
Quests; LoadQuests();
#else
new Dictionary<ushort, QuestRoot>();
#endif #endif
}
return _quests ?? throw new InvalidOperationException("quest data is not initialized");
}
public static Stream QuestSchema => public static Stream QuestSchema =>
typeof(AssemblyQuestLoader).Assembly.GetManifestResourceStream("Questionable.QuestPaths.QuestSchema")!; typeof(AssemblyQuestLoader).Assembly.GetManifestResourceStream("Questionable.QuestPaths.QuestSchema")!;
private static void AddQuest(ushort questId, QuestRoot root) => _quests![questId] = root;
} }

View File

@ -9,35 +9,34 @@
<DebugType>none</DebugType> <DebugType>none</DebugType>
<PathMap Condition="$(SolutionDir) != ''">$(SolutionDir)=X:\</PathMap> <PathMap Condition="$(SolutionDir) != ''">$(SolutionDir)=X:\</PathMap>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles> <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<Platforms>x64</Platforms>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Questionable.Model\Questionable.Model.csproj"/> <ProjectReference Include="..\Questionable.Model\Questionable.Model.csproj" />
<ProjectReference Include="..\QuestPathGenerator\QuestPathGenerator.csproj" <ProjectReference Include="..\QuestPathGenerator\QuestPathGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
OutputItemType="Analyzer"
ReferenceOutputAssembly="false"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Remove="quest-v1.json"/> <None Remove="quest-v1.json" />
<EmbeddedResource Include="quest-v1.json"> <EmbeddedResource Include="quest-v1.json">
<LogicalName>Questionable.QuestPaths.QuestSchema</LogicalName> <LogicalName>Questionable.QuestPaths.QuestSchema</LogicalName>
</EmbeddedResource> </EmbeddedResource>
<AdditionalFiles Include="quest-v1.json"/> <AdditionalFiles Include="quest-v1.json" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition="'$(Configuration)' == 'Release'"> <ItemGroup Condition="'$(Configuration)' == 'Release'">
<None Remove="2.x - A Realm Reborn"/> <None Remove="2.x - A Realm Reborn" />
<None Remove="3.x - Heavensward"/> <None Remove="3.x - Heavensward" />
<None Remove="4.x - Stormblood"/> <None Remove="4.x - Stormblood" />
<None Remove="5.x - Shadowbringers"/> <None Remove="5.x - Shadowbringers" />
<None Remove="6.x - Endwalker"/> <None Remove="6.x - Endwalker" />
<None Remove="7.x - Dawntrail"/> <None Remove="7.x - Dawntrail" />
<AdditionalFiles Include="2.x - A Realm Reborn\**\*.json"/> <AdditionalFiles Include="2.x - A Realm Reborn\**\*.json" />
<AdditionalFiles Include="3.x - Heavensward\**\*.json"/> <AdditionalFiles Include="3.x - Heavensward\**\*.json" />
<AdditionalFiles Include="4.x - Stormblood\**\*.json"/> <AdditionalFiles Include="4.x - Stormblood\**\*.json" />
<AdditionalFiles Include="5.x - Shadowbringers\**\*.json"/> <AdditionalFiles Include="5.x - Shadowbringers\**\*.json" />
<AdditionalFiles Include="6.x - Endwalker\**\*.json" /> <AdditionalFiles Include="6.x - Endwalker\**\*.json" />
<AdditionalFiles Include="7.x - Dawntrail\**\*.json"/> <AdditionalFiles Include="7.x - Dawntrail\**\*.json" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -7,6 +7,7 @@
<PathMap Condition="$(SolutionDir) != ''">$(SolutionDir)=X:\</PathMap> <PathMap Condition="$(SolutionDir) != ''">$(SolutionDir)=X:\</PathMap>
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile> <RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
<DebugType>portable</DebugType> <DebugType>portable</DebugType>
<Platforms>x64</Platforms>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -1,46 +1,48 @@
 
Microsoft Visual Studio Solution File, Format Version 12.00 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 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 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 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 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 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 EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|x64 = Debug|x64
Release|Any CPU = Release|Any CPU Release|x64 = Release|x64
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
{C91EEF13-A1AC-4A40-B695-DD4E378E5989}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C91EEF13-A1AC-4A40-B695-DD4E378E5989}.Debug|x64.ActiveCfg = ExportRelease|x64
{C91EEF13-A1AC-4A40-B695-DD4E378E5989}.Debug|Any CPU.Build.0 = Debug|Any CPU {C91EEF13-A1AC-4A40-B695-DD4E378E5989}.Debug|x64.Build.0 = ExportRelease|x64
{C91EEF13-A1AC-4A40-B695-DD4E378E5989}.Release|Any CPU.ActiveCfg = Release|Any CPU {EEDE3BBE-E260-445E-8FB3-1264E0CBBE91}.Debug|x64.ActiveCfg = ExportRelease|x64
{C91EEF13-A1AC-4A40-B695-DD4E378E5989}.Release|Any CPU.Build.0 = Release|Any CPU {EEDE3BBE-E260-445E-8FB3-1264E0CBBE91}.Debug|x64.Build.0 = ExportRelease|x64
{EEDE3BBE-E260-445E-8FB3-1264E0CBBE91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7A136F28-8D5C-478D-B993-0F39F1451A47}.Debug|x64.ActiveCfg = Debug|x64
{EEDE3BBE-E260-445E-8FB3-1264E0CBBE91}.Debug|Any CPU.Build.0 = Debug|Any CPU {7A136F28-8D5C-478D-B993-0F39F1451A47}.Debug|x64.Build.0 = Debug|x64
{EEDE3BBE-E260-445E-8FB3-1264E0CBBE91}.Release|Any CPU.ActiveCfg = Release|Any CPU {7A136F28-8D5C-478D-B993-0F39F1451A47}.Release|x64.ActiveCfg = Release|x64
{EEDE3BBE-E260-445E-8FB3-1264E0CBBE91}.Release|Any CPU.Build.0 = Release|Any CPU {7A136F28-8D5C-478D-B993-0F39F1451A47}.Release|x64.Build.0 = Release|x64
{7A136F28-8D5C-478D-B993-0F39F1451A47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DFFD56A8-FA89-4585-A47B-C6AB27B65F0F}.Debug|x64.ActiveCfg = Debug|x64
{7A136F28-8D5C-478D-B993-0F39F1451A47}.Debug|Any CPU.Build.0 = Debug|Any CPU {DFFD56A8-FA89-4585-A47B-C6AB27B65F0F}.Debug|x64.Build.0 = Debug|x64
{7A136F28-8D5C-478D-B993-0F39F1451A47}.Release|Any CPU.ActiveCfg = Release|Any CPU {DFFD56A8-FA89-4585-A47B-C6AB27B65F0F}.Release|x64.ActiveCfg = Release|x64
{7A136F28-8D5C-478D-B993-0F39F1451A47}.Release|Any CPU.Build.0 = Release|Any CPU {DFFD56A8-FA89-4585-A47B-C6AB27B65F0F}.Release|x64.Build.0 = Release|x64
{DFFD56A8-FA89-4585-A47B-C6AB27B65F0F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E15144A5-AFF5-4D86-9561-AFF7DF7F505D}.Debug|x64.ActiveCfg = Debug|x64
{DFFD56A8-FA89-4585-A47B-C6AB27B65F0F}.Debug|Any CPU.Build.0 = Debug|Any CPU {E15144A5-AFF5-4D86-9561-AFF7DF7F505D}.Debug|x64.Build.0 = Debug|x64
{DFFD56A8-FA89-4585-A47B-C6AB27B65F0F}.Release|Any CPU.ActiveCfg = Release|Any CPU {E15144A5-AFF5-4D86-9561-AFF7DF7F505D}.Release|x64.ActiveCfg = Release|x64
{DFFD56A8-FA89-4585-A47B-C6AB27B65F0F}.Release|Any CPU.Build.0 = Release|Any CPU {E15144A5-AFF5-4D86-9561-AFF7DF7F505D}.Release|x64.Build.0 = Release|x64
{E15144A5-AFF5-4D86-9561-AFF7DF7F505D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4FD6F346-8961-4BD5-BDA2-E5F426DE4FC7}.Debug|x64.ActiveCfg = Debug|x64
{E15144A5-AFF5-4D86-9561-AFF7DF7F505D}.Debug|Any CPU.Build.0 = Debug|Any CPU {4FD6F346-8961-4BD5-BDA2-E5F426DE4FC7}.Debug|x64.Build.0 = Debug|x64
{E15144A5-AFF5-4D86-9561-AFF7DF7F505D}.Release|Any CPU.ActiveCfg = Release|Any CPU {4FD6F346-8961-4BD5-BDA2-E5F426DE4FC7}.Release|x64.ActiveCfg = Release|x64
{E15144A5-AFF5-4D86-9561-AFF7DF7F505D}.Release|Any CPU.Build.0 = Release|Any CPU {4FD6F346-8961-4BD5-BDA2-E5F426DE4FC7}.Release|x64.Build.0 = Release|x64
{4FD6F346-8961-4BD5-BDA2-E5F426DE4FC7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU EndGlobalSection
{4FD6F346-8961-4BD5-BDA2-E5F426DE4FC7}.Debug|Any CPU.Build.0 = Debug|Any CPU GlobalSection(SolutionProperties) = preSolution
{4FD6F346-8961-4BD5-BDA2-E5F426DE4FC7}.Release|Any CPU.ActiveCfg = Release|Any CPU HideSolutionNode = FALSE
{4FD6F346-8961-4BD5-BDA2-E5F426DE4FC7}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

View File

@ -423,7 +423,6 @@ internal sealed class QuestController
_logger.LogError(e, "Failed to update task {TaskName}", _currentTask.ToString()); _logger.LogError(e, "Failed to update task {TaskName}", _currentTask.ToString());
_chatGui.PrintError( _chatGui.PrintError(
$"[Questionable] Failed to update task '{_currentTask}', please check /xllog for details."); $"[Questionable] Failed to update task '{_currentTask}', please check /xllog for details.");
Stop("Task failed to start");
Stop("Task failed to update"); Stop("Task failed to update");
return; return;
} }

View File

@ -63,7 +63,7 @@ internal sealed class QuestRegistry
} }
ValidateQuests(); ValidateQuests();
_logger.LogInformation("Loaded {Count} quests", _quests.Count); _logger.LogInformation("Loaded {Count} quests in total", _quests.Count);
} }
[Conditional("RELEASE")] [Conditional("RELEASE")]
@ -82,6 +82,8 @@ internal sealed class QuestRegistry
}; };
_quests[questId] = quest; _quests[questId] = quest;
} }
_logger.LogInformation("Loaded {Count} quests from assembly", _quests.Count);
} }
[Conditional("DEBUG")] [Conditional("DEBUG")]

View File

@ -1,4 +1,5 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -38,26 +39,35 @@ internal sealed class QuestValidator
{ {
Task.Factory.StartNew(() => 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; foreach (var issue in validator.Validate(quest))
_logger.Log(level, {
"Validation failed: {QuestId} ({QuestName}) / {QuestSequence} / {QuestStep} - {Description}", var level = issue.Severity == EIssueSeverity.Error
issue.QuestId, quest.Info.Name, issue.Sequence, issue.Step, issue.Description); ? LogLevel.Warning
_validationIssues.Add(issue); : 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) _validationIssues = _validationIssues.OrderBy(x => x.QuestId)
.ThenBy(x => x.Sequence) .ThenBy(x => x.Sequence)
.ThenBy(x => x.Step) .ThenBy(x => x.Step)
.ThenBy(x => x.Description) .ThenBy(x => x.Description)
.ToList(); .ToList();
}
catch (Exception e)
{
_logger.LogError(e, "Unable to validate quests");
}
}, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default); }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default);
} }
} }

View File

@ -228,10 +228,10 @@ internal sealed class QuestSelectionWindow : LWindow
ImGui.SameLine(); ImGui.SameLine();
if (knownQuest != null && if (knownQuest != null &&
knownQuest.FindSequence(0)?.LastStep()?.InteractionType == EInteractionType.AcceptQuest /* && knownQuest.FindSequence(0)?.LastStep()?.InteractionType == EInteractionType.AcceptQuest &&
!_gameFunctions.IsQuestAccepted(quest.QuestId) && !_gameFunctions.IsQuestAccepted(quest.QuestId) &&
!_gameFunctions.IsQuestLocked(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); ImGui.BeginDisabled(_questController.NextQuest != null || _questController.SimulatedQuest != null);