diff --git a/.gitignore b/.gitignore
index 05dc5493..f0fb17c2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,5 @@
-/.idea
+obj/
+bin/
+/.idea
+/.vs
*.user
diff --git a/QuestPathGenerator/QuestPathGenerator.csproj b/QuestPathGenerator/QuestPathGenerator.csproj
new file mode 100644
index 00000000..b62d2878
--- /dev/null
+++ b/QuestPathGenerator/QuestPathGenerator.csproj
@@ -0,0 +1,37 @@
+
+
+ netstandard2.0
+ false
+ 12
+ enable
+ true
+ Questionable.QuestPathGenerator
+ portable
+
+ true
+ true
+
+ QuestPathGenerator
+ true
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/QuestPathGenerator/QuestSourceGenerator.cs b/QuestPathGenerator/QuestSourceGenerator.cs
new file mode 100644
index 00000000..9bc6cc29
--- /dev/null
+++ b/QuestPathGenerator/QuestSourceGenerator.cs
@@ -0,0 +1,316 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text.Json;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Questionable.Model.V1;
+using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
+using static Questionable.QuestPathGenerator.RoslynShortcuts;
+
+namespace Questionable.QuestPathGenerator;
+
+///
+/// A sample source generator that creates C# classes based on the text file (in this case, Domain Driven Design ubiquitous language registry).
+/// When using a simple text file as a baseline, we can create a non-incremental source generator.
+///
+[Generator]
+public class QuestSourceGenerator : ISourceGenerator
+{
+ public void Initialize(GeneratorInitializationContext context)
+ {
+ // No initialization required for this generator.
+ }
+
+ public void Execute(GeneratorExecutionContext context)
+ {
+ List<(ushort, QuestData)> quests = [];
+
+ // Go through all files marked as an Additional File in file properties.
+ foreach (var additionalFile in context.AdditionalFiles)
+ {
+ if (additionalFile == null)
+ continue;
+
+ if (Path.GetExtension(additionalFile.Path) != ".json")
+ continue;
+
+ string name = Path.GetFileName(additionalFile.Path);
+ ushort id = ushort.Parse(name.Substring(0, name.IndexOf('_')));
+
+ var text = additionalFile.GetText();
+ if (text == null)
+ continue;
+
+ var quest = JsonSerializer.Deserialize(text.ToString())!;
+ quests.Add((id, quest));
+ }
+
+ quests = quests.OrderBy(x => x.Item1).ToList();
+
+ var code =
+ CompilationUnit()
+ .WithUsings(
+ List(
+ new[]
+ {
+ UsingDirective(
+ IdentifierName("System")),
+ UsingDirective(
+ QualifiedName(
+ IdentifierName("System"),
+ IdentifierName("Numerics"))),
+ UsingDirective(
+ QualifiedName(
+ IdentifierName("System"),
+ IdentifierName("IO"))),
+ UsingDirective(
+ QualifiedName(
+ QualifiedName(
+ IdentifierName("System"), IdentifierName("Collections")),
+ IdentifierName("Generic"))),
+ UsingDirective(
+ QualifiedName(
+ QualifiedName(
+ IdentifierName("Questionable"),
+ IdentifierName("Model")),
+ IdentifierName("V1")))
+ }))
+ .WithMembers(
+ SingletonList(
+ FileScopedNamespaceDeclaration(
+ QualifiedName(
+ IdentifierName("Questionable"),
+ IdentifierName("QuestPaths")))
+ .WithMembers(
+ SingletonList(
+ ClassDeclaration("AssemblyQuestLoader")
+ .WithModifiers(
+ TokenList(
+ [
+ Token(SyntaxKind.PartialKeyword)
+ ]))
+ .WithMembers(
+ SingletonList(
+ FieldDeclaration(
+ VariableDeclaration(
+ GenericName(
+ Identifier("IReadOnlyDictionary"))
+ .WithTypeArgumentList(
+ TypeArgumentList(
+ SeparatedList(
+ new SyntaxNodeOrToken[]
+ {
+ PredefinedType(
+ Token(SyntaxKind
+ .UShortKeyword)),
+ Token(SyntaxKind.CommaToken),
+ IdentifierName("QuestData")
+ }))))
+ .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(
+ "QuestData")
+ }))))
+ .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();
+
+ // Add the source code to the compilation.
+ context.AddSource("AssemblyQuestLoader.g.cs", code.ToFullString());
+ }
+
+ private static IEnumerable CreateQuestInitializer(ushort questId, QuestData quest)
+ {
+ return new SyntaxNodeOrToken[]
+ {
+ InitializerExpression(
+ SyntaxKind.ComplexElementInitializerExpression,
+ SeparatedList(
+ new SyntaxNodeOrToken[]
+ {
+ LiteralExpression(
+ SyntaxKind.NumericLiteralExpression,
+ Literal(questId)),
+ Token(SyntaxKind.CommaToken),
+ ObjectCreationExpression(
+ IdentifierName(nameof(QuestData)))
+ .WithInitializer(
+ InitializerExpression(
+ SyntaxKind.ObjectInitializerExpression,
+ SeparatedList(
+ SyntaxNodeList(
+ Assignment(nameof(QuestData.Author), quest.Author, null)
+ .AsSyntaxNodeOrToken(),
+ AssignmentList(nameof(QuestData.Contributors), quest.Contributors)
+ .AsSyntaxNodeOrToken(),
+ Assignment(nameof(QuestData.Comment), quest.Comment, null)
+ .AsSyntaxNodeOrToken(),
+ AssignmentList(nameof(QuestData.TerritoryBlacklist),
+ quest.TerritoryBlacklist).AsSyntaxNodeOrToken(),
+ AssignmentExpression(
+ SyntaxKind.SimpleAssignmentExpression,
+ IdentifierName(nameof(QuestData.QuestSequence)),
+ CreateQuestSequence(quest.QuestSequence))
+ ))))
+ })),
+ Token(SyntaxKind.CommaToken)
+ };
+ }
+
+ private static ExpressionSyntax CreateQuestSequence(List sequences)
+ {
+ return CollectionExpression(
+ SeparatedList(
+ sequences.SelectMany(sequence => new SyntaxNodeOrToken[]
+ {
+ ExpressionElement(
+ ObjectCreationExpression(
+ IdentifierName(nameof(QuestSequence)))
+ .WithInitializer(
+ InitializerExpression(
+ SyntaxKind.ObjectInitializerExpression,
+ SeparatedList(
+ SyntaxNodeList(
+ Assignment(nameof(QuestSequence.Sequence), sequence.Sequence, null)
+ .AsSyntaxNodeOrToken(),
+ Assignment(nameof(QuestSequence.Comment), sequence.Comment, null)
+ .AsSyntaxNodeOrToken(),
+ AssignmentExpression(
+ SyntaxKind.SimpleAssignmentExpression,
+ IdentifierName(nameof(QuestSequence.Steps)),
+ CreateQuestSteps(sequence.Steps))))))),
+ Token(SyntaxKind.CommaToken),
+ }.ToArray())));
+ }
+
+ private static ExpressionSyntax CreateQuestSteps(List steps)
+ {
+ QuestStep emptyStep = new();
+ return CollectionExpression(
+ SeparatedList(
+ steps.SelectMany(step => new SyntaxNodeOrToken[]
+ {
+ ExpressionElement(
+ ObjectCreationExpression(
+ IdentifierName(nameof(QuestStep)))
+ .WithArgumentList(
+ ArgumentList(
+ SeparatedList(
+ new SyntaxNodeOrToken[]
+ {
+ Argument(LiteralValue(step.InteractionType)),
+ Token(SyntaxKind.CommaToken),
+ Argument(LiteralValue(step.DataId)),
+ Token(SyntaxKind.CommaToken),
+ Argument(LiteralValue(step.Position)),
+ Token(SyntaxKind.CommaToken),
+ Argument(LiteralValue(step.TerritoryId))
+ })))
+ .WithInitializer(
+ InitializerExpression(
+ SyntaxKind.ObjectInitializerExpression,
+ SeparatedList(
+ SyntaxNodeList(
+ Assignment(nameof(QuestStep.StopDistance), step.StopDistance,
+ emptyStep.StopDistance)
+ .AsSyntaxNodeOrToken(),
+ Assignment(nameof(QuestStep.TargetTerritoryId), step.TargetTerritoryId,
+ emptyStep.TargetTerritoryId)
+ .AsSyntaxNodeOrToken(),
+ Assignment(nameof(QuestStep.Disabled), step.Disabled, emptyStep.Disabled)
+ .AsSyntaxNodeOrToken(),
+ Assignment(nameof(QuestStep.DisableNavmesh), step.DisableNavmesh,
+ emptyStep.DisableNavmesh)
+ .AsSyntaxNodeOrToken(),
+ Assignment(nameof(QuestStep.Mount), step.Mount, emptyStep.Mount)
+ .AsSyntaxNodeOrToken(),
+ Assignment(nameof(QuestStep.Fly), step.Fly, emptyStep.Fly)
+ .AsSyntaxNodeOrToken(),
+ Assignment(nameof(QuestStep.Sprint), step.Sprint, emptyStep.Sprint)
+ .AsSyntaxNodeOrToken(),
+ Assignment(nameof(QuestStep.Comment), step.Comment, emptyStep.Comment)
+ .AsSyntaxNodeOrToken(),
+ Assignment(nameof(QuestStep.AetheryteShortcut), step.AetheryteShortcut,
+ emptyStep.AetheryteShortcut)
+ .AsSyntaxNodeOrToken(),
+ Assignment(nameof(QuestStep.AethernetShortcut), step.AethernetShortcut,
+ emptyStep.AethernetShortcut)
+ .AsSyntaxNodeOrToken(),
+ Assignment(nameof(QuestStep.AetherCurrentId), step.AetherCurrentId,
+ emptyStep.AetherCurrentId)
+ .AsSyntaxNodeOrToken(),
+ Assignment(nameof(QuestStep.ItemId), step.ItemId, emptyStep.ItemId)
+ .AsSyntaxNodeOrToken(),
+ Assignment(nameof(QuestStep.GroundTarget), step.GroundTarget,
+ emptyStep.GroundTarget)
+ .AsSyntaxNodeOrToken(),
+ Assignment(nameof(QuestStep.Emote), step.Emote, emptyStep.Emote)
+ .AsSyntaxNodeOrToken(),
+ Assignment(nameof(QuestStep.ChatMessage), step.ChatMessage,
+ emptyStep.ChatMessage)
+ .AsSyntaxNodeOrToken(),
+ Assignment(nameof(QuestStep.EnemySpawnType), step.EnemySpawnType,
+ emptyStep.EnemySpawnType)
+ .AsSyntaxNodeOrToken(),
+ AssignmentList(nameof(QuestStep.KillEnemyDataIds), step.KillEnemyDataIds)
+ .AsSyntaxNodeOrToken(),
+ Assignment(nameof(QuestStep.JumpDestination), step.JumpDestination,
+ emptyStep.JumpDestination)
+ .AsSyntaxNodeOrToken(),
+ Assignment(nameof(QuestStep.ContentFinderConditionId),
+ step.ContentFinderConditionId, emptyStep.ContentFinderConditionId)
+ .AsSyntaxNodeOrToken(),
+ AssignmentList(nameof(QuestStep.SkipIf), step.SkipIf)
+ .AsSyntaxNodeOrToken(),
+ AssignmentList(nameof(QuestStep.CompletionQuestVariablesFlags),
+ step.CompletionQuestVariablesFlags)
+ .AsSyntaxNodeOrToken(),
+ AssignmentList(nameof(QuestStep.DialogueChoices), step.DialogueChoices)
+ .AsSyntaxNodeOrToken()))))),
+ Token(SyntaxKind.CommaToken),
+ }.ToArray())));
+ }
+}
diff --git a/QuestPathGenerator/RoslynShortcuts.cs b/QuestPathGenerator/RoslynShortcuts.cs
new file mode 100644
index 00000000..545cb27a
--- /dev/null
+++ b/QuestPathGenerator/RoslynShortcuts.cs
@@ -0,0 +1,208 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Numerics;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Questionable.Model.V1;
+using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
+
+namespace Questionable.QuestPathGenerator;
+
+public static class RoslynShortcuts
+{
+ public static IEnumerable SyntaxNodeList(params SyntaxNodeOrToken?[] nodes)
+ {
+ nodes = nodes.Where(x => x != null).ToArray();
+ if (nodes.Length == 0)
+ return [];
+
+ List list = new();
+ for (int i = 0; i < nodes.Length; ++i)
+ {
+ if (i > 0)
+ list.Add(Token(SyntaxKind.CommaToken));
+ list.Add(nodes[i].GetValueOrDefault());
+ }
+
+ return list;
+ }
+
+ public static ExpressionSyntax LiteralValue(T? value)
+ {
+ if (value is string s)
+ return LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(s));
+ else if (value is bool b)
+ return LiteralExpression(b ? SyntaxKind.TrueLiteralExpression : SyntaxKind.FalseLiteralExpression);
+ else if (value is short i16)
+ return LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(i16));
+ else if (value is int i32)
+ return LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(i32));
+ else if (value is ushort u16)
+ return LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(u16));
+ else if (value is uint u32)
+ return LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(u32));
+ else if (value is float f)
+ return LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(f));
+ else if (value != null && value.GetType().IsEnum)
+ return MemberAccessExpression(
+ SyntaxKind.SimpleMemberAccessExpression,
+ IdentifierName(value.GetType().Name),
+ IdentifierName(value.GetType().GetEnumName(value)!));
+ else if (value is Vector3 vector)
+ {
+ return ObjectCreationExpression(
+ IdentifierName(nameof(Vector3)))
+ .WithArgumentList(
+ ArgumentList(
+ SeparatedList(
+ new SyntaxNodeOrToken[]
+ {
+ Argument(LiteralValue(vector.X)),
+ Token(SyntaxKind.CommaToken),
+ Argument(LiteralValue(vector.Y)),
+ Token(SyntaxKind.CommaToken),
+ Argument(LiteralValue(vector.Z))
+ })));
+ }
+ else if (value is AethernetShortcut aethernetShortcut)
+ {
+ return ObjectCreationExpression(
+ IdentifierName(nameof(AethernetShortcut)))
+ .WithInitializer(
+ InitializerExpression(
+ SyntaxKind.ObjectInitializerExpression,
+ SeparatedList(
+ SyntaxNodeList(
+ Assignment(nameof(AethernetShortcut.From), aethernetShortcut.From,
+ null)
+ .AsSyntaxNodeOrToken(),
+ Assignment(nameof(AethernetShortcut.To), aethernetShortcut.To,
+ null)
+ .AsSyntaxNodeOrToken()))));
+ }
+ else if (value is ChatMessage chatMessage)
+ {
+ ChatMessage emptyMessage = new();
+ return ObjectCreationExpression(
+ IdentifierName(nameof(ChatMessage)))
+ .WithInitializer(
+ InitializerExpression(
+ SyntaxKind.ObjectInitializerExpression,
+ SeparatedList(
+ SyntaxNodeList(
+ Assignment(nameof(ChatMessage.ExcelSheet), chatMessage.ExcelSheet,
+ emptyMessage.ExcelSheet)
+ .AsSyntaxNodeOrToken(),
+ Assignment(nameof(ChatMessage.Key), chatMessage.Key,
+ emptyMessage.Key)
+ .AsSyntaxNodeOrToken()))));
+ }
+ else if (value is DialogueChoice dialogueChoice)
+ {
+ DialogueChoice emptyChoice = new();
+ return ObjectCreationExpression(
+ IdentifierName(nameof(DialogueChoice)))
+ .WithInitializer(
+ InitializerExpression(
+ SyntaxKind.ObjectInitializerExpression,
+ SeparatedList(
+ SyntaxNodeList(
+ Assignment(nameof(DialogueChoice.Type), dialogueChoice.Type, null)
+ .AsSyntaxNodeOrToken(),
+ Assignment(nameof(DialogueChoice.ExcelSheet), dialogueChoice.ExcelSheet,
+ emptyChoice.ExcelSheet)
+ .AsSyntaxNodeOrToken(),
+ Assignment(nameof(DialogueChoice.Prompt), dialogueChoice.Prompt, emptyChoice.Prompt)
+ .AsSyntaxNodeOrToken(),
+ Assignment(nameof(DialogueChoice.Yes), dialogueChoice.Yes, emptyChoice.Yes)
+ .AsSyntaxNodeOrToken(),
+ Assignment(nameof(DialogueChoice.Answer), dialogueChoice.Answer, emptyChoice.Answer)
+ .AsSyntaxNodeOrToken(),
+ Assignment(nameof(DialogueChoice.DataId), dialogueChoice.DataId, emptyChoice.DataId)
+ .AsSyntaxNodeOrToken()))));
+ }
+ else if (value is JumpDestination jumpDestination)
+ {
+ return ObjectCreationExpression(
+ IdentifierName(nameof(JumpDestination)))
+ .WithInitializer(
+ InitializerExpression(
+ SyntaxKind.ObjectInitializerExpression,
+ SeparatedList(
+ SyntaxNodeList(
+ Assignment(nameof(JumpDestination.Position), jumpDestination.Position, null)
+ .AsSyntaxNodeOrToken(),
+ Assignment(nameof(JumpDestination.StopDistance), jumpDestination.StopDistance, null)
+ .AsSyntaxNodeOrToken(),
+ Assignment(nameof(JumpDestination.DelaySeconds), jumpDestination.DelaySeconds, null)
+ .AsSyntaxNodeOrToken()))));
+ }
+ else if (value is ExcelRef excelRef)
+ {
+ if (excelRef.Type == ExcelRef.EType.Key)
+ {
+ return ObjectCreationExpression(
+ IdentifierName(nameof(ExcelRef)))
+ .WithArgumentList(
+ ArgumentList(
+ SingletonSeparatedList(
+ Argument(LiteralValue(excelRef.AsKey())))));
+ }
+ else if (excelRef.Type == ExcelRef.EType.RowId)
+ {
+ return ObjectCreationExpression(
+ IdentifierName(nameof(ExcelRef)))
+ .WithArgumentList(
+ ArgumentList(
+ SingletonSeparatedList(
+ Argument(LiteralValue(excelRef.AsRowId())))));
+ }
+ else
+ throw new Exception($"Unsupported ExcelRef type {excelRef.Type}");
+ }
+ else if (value is null)
+ return LiteralExpression(SyntaxKind.NullLiteralExpression);
+ else
+ throw new Exception($"Unsupported data type {value.GetType()} = {value}");
+ }
+
+ public static AssignmentExpressionSyntax? Assignment(string name, T? value, T? defaultValue)
+ {
+ if (value == null && defaultValue == null)
+ return null;
+
+ if (value != null && defaultValue != null && value.Equals(defaultValue))
+ return null;
+
+ return AssignmentExpression(
+ SyntaxKind.SimpleAssignmentExpression,
+ IdentifierName(name),
+ LiteralValue(value));
+ }
+
+ public static AssignmentExpressionSyntax? AssignmentList(string name, IEnumerable value)
+ {
+ IEnumerable list = value.ToList();
+ if (!list.Any())
+ return null;
+
+ return AssignmentExpression(
+ SyntaxKind.SimpleAssignmentExpression,
+ IdentifierName(name),
+ CollectionExpression(
+ SeparatedList(
+ SyntaxNodeList(list.Select(x => ExpressionElement(
+ LiteralValue(x)).AsSyntaxNodeOrToken()).ToArray())
+ )));
+ }
+
+ public static SyntaxNodeOrToken? AsSyntaxNodeOrToken(this SyntaxNode? node)
+ {
+ if (node == null)
+ return null;
+
+ return node;
+ }
+}
diff --git a/QuestPathGenerator/packages.lock.json b/QuestPathGenerator/packages.lock.json
new file mode 100644
index 00000000..a9d05083
--- /dev/null
+++ b/QuestPathGenerator/packages.lock.json
@@ -0,0 +1,244 @@
+{
+ "version": 1,
+ "dependencies": {
+ ".NETStandard,Version=v2.0": {
+ "Microsoft.CodeAnalysis.Analyzers": {
+ "type": "Direct",
+ "requested": "[3.3.4, )",
+ "resolved": "3.3.4",
+ "contentHash": "AxkxcPR+rheX0SmvpLVIGLhOUXAKG56a64kV9VQZ4y9gR9ZmPXnqZvHJnmwLSwzrEP6junUF11vuc+aqo5r68g=="
+ },
+ "Microsoft.CodeAnalysis.CSharp": {
+ "type": "Direct",
+ "requested": "[4.9.2, )",
+ "resolved": "4.9.2",
+ "contentHash": "HGIo7E9Mf3exAJbUdYpDFfLoYkSVaHDJXPyusWTYUTBaOPCowGw+Gap5McE1w+K+ryIXre72oiqL88sQHmHBmg==",
+ "dependencies": {
+ "Microsoft.CodeAnalysis.Common": "[4.9.2]"
+ }
+ },
+ "Microsoft.CodeAnalysis.CSharp.Workspaces": {
+ "type": "Direct",
+ "requested": "[4.9.2, )",
+ "resolved": "4.9.2",
+ "contentHash": "c74oxEil3fiZ3nXchnIgY6mXS4roHGiQBT6p3X6dMWokVqluHiqi3PNcXyxH8N/w28rQeXprF3mca83rPPNrMw==",
+ "dependencies": {
+ "Humanizer.Core": "2.14.1",
+ "Microsoft.CodeAnalysis.CSharp": "[4.9.2]",
+ "Microsoft.CodeAnalysis.Common": "[4.9.2]",
+ "Microsoft.CodeAnalysis.Workspaces.Common": "[4.9.2]"
+ }
+ },
+ "NETStandard.Library": {
+ "type": "Direct",
+ "requested": "[2.0.3, )",
+ "resolved": "2.0.3",
+ "contentHash": "st47PosZSHrjECdjeIzZQbzivYBJFv6P2nv4cj2ypdI204DO+vZ7l5raGMiX4eXMJ53RfOIg+/s4DHVZ54Nu2A==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0"
+ }
+ },
+ "System.Text.Json": {
+ "type": "Direct",
+ "requested": "[8.0.3, )",
+ "resolved": "8.0.3",
+ "contentHash": "hpagS9joOwv6efWfrMmV9MjQXpiXZH72PgN067Ysfr6AWMSD1/1hEcvh/U5mUpPLezEWsOJSuVrmqDIVD958iA==",
+ "dependencies": {
+ "Microsoft.Bcl.AsyncInterfaces": "8.0.0",
+ "System.Buffers": "4.5.1",
+ "System.Memory": "4.5.5",
+ "System.Runtime.CompilerServices.Unsafe": "6.0.0",
+ "System.Text.Encodings.Web": "8.0.0",
+ "System.Threading.Tasks.Extensions": "4.5.4"
+ }
+ },
+ "Humanizer.Core": {
+ "type": "Transitive",
+ "resolved": "2.14.1",
+ "contentHash": "lQKvtaTDOXnoVJ20ibTuSIOf2i0uO0MPbDhd1jm238I+U/2ZnRENj0cktKZhtchBMtCUSRQ5v4xBCUbKNmyVMw=="
+ },
+ "Microsoft.Bcl.AsyncInterfaces": {
+ "type": "Transitive",
+ "resolved": "8.0.0",
+ "contentHash": "3WA9q9yVqJp222P3x1wYIGDAkpjAku0TMUaaQV22g6L67AI0LdOIrVS7Ht2vJfLHGSPVuqN94vIr15qn+HEkHw==",
+ "dependencies": {
+ "System.Threading.Tasks.Extensions": "4.5.4"
+ }
+ },
+ "Microsoft.CodeAnalysis.Common": {
+ "type": "Transitive",
+ "resolved": "4.9.2",
+ "contentHash": "M5PThug7b2AdxL7xKmQs50KzAQTl9jENw5jMT3iUt16k+DAFlw1S87juU3UuPs3gvBm8trMBSOEvSFDr31c9Vw==",
+ "dependencies": {
+ "Microsoft.CodeAnalysis.Analyzers": "3.3.4",
+ "System.Collections.Immutable": "8.0.0",
+ "System.Memory": "4.5.5",
+ "System.Reflection.Metadata": "8.0.0",
+ "System.Runtime.CompilerServices.Unsafe": "6.0.0",
+ "System.Text.Encoding.CodePages": "8.0.0",
+ "System.Threading.Tasks.Extensions": "4.5.4"
+ }
+ },
+ "Microsoft.CodeAnalysis.Workspaces.Common": {
+ "type": "Transitive",
+ "resolved": "4.9.2",
+ "contentHash": "sgBlkBjKwUdpbtwM7SnBdOxvQxuaTtO9F8QgvKY5cH/OnlwDTZqmkK8hfDbhxv9wnN2wME10BL2vIv1fLJwFGA==",
+ "dependencies": {
+ "Humanizer.Core": "2.14.1",
+ "Microsoft.Bcl.AsyncInterfaces": "8.0.0",
+ "Microsoft.CodeAnalysis.Common": "[4.9.2]",
+ "System.Composition": "8.0.0",
+ "System.IO.Pipelines": "8.0.0",
+ "System.Threading.Channels": "8.0.0"
+ }
+ },
+ "Microsoft.NETCore.Platforms": {
+ "type": "Transitive",
+ "resolved": "1.1.0",
+ "contentHash": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A=="
+ },
+ "System.Buffers": {
+ "type": "Transitive",
+ "resolved": "4.5.1",
+ "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg=="
+ },
+ "System.Collections.Immutable": {
+ "type": "Transitive",
+ "resolved": "8.0.0",
+ "contentHash": "AurL6Y5BA1WotzlEvVaIDpqzpIPvYnnldxru8oXJU2yFxFUy3+pNXjXd1ymO+RA0rq0+590Q8gaz2l3Sr7fmqg==",
+ "dependencies": {
+ "System.Memory": "4.5.5",
+ "System.Runtime.CompilerServices.Unsafe": "6.0.0"
+ }
+ },
+ "System.Composition": {
+ "type": "Transitive",
+ "resolved": "8.0.0",
+ "contentHash": "E9oO9olNNxA39J8CxQwf7ceIPm+j/B/PhYpyK9M4LhN/OLLRw6u5fNInkhVqaWueMB9iXxYqnwqwgz+W91loIA==",
+ "dependencies": {
+ "System.Composition.AttributedModel": "8.0.0",
+ "System.Composition.Convention": "8.0.0",
+ "System.Composition.Hosting": "8.0.0",
+ "System.Composition.Runtime": "8.0.0",
+ "System.Composition.TypedParts": "8.0.0"
+ }
+ },
+ "System.Composition.AttributedModel": {
+ "type": "Transitive",
+ "resolved": "8.0.0",
+ "contentHash": "NyElSuvmBMYdn2iPG0n29i7Igu0bq99izOP3MAtEwskY3OP9jqsavvVmPn9lesVaj/KT/o/QkNjA43dOJTsDQw=="
+ },
+ "System.Composition.Convention": {
+ "type": "Transitive",
+ "resolved": "8.0.0",
+ "contentHash": "UuVkc1B3vQU/LzEbWLMZ1aYVssv4rpShzf8wPEyrUqoGNqdYKREmB8bXR73heOMKkwS6ZnPz3PjGODT2MenukQ==",
+ "dependencies": {
+ "System.Composition.AttributedModel": "8.0.0"
+ }
+ },
+ "System.Composition.Hosting": {
+ "type": "Transitive",
+ "resolved": "8.0.0",
+ "contentHash": "qwbONqoxlazxcbiohvb3t1JWZgKIKcRdXS5uEeLbo5wtuBupIbAvdC3PYTAeBCZrZeERvrtAbhYHuuS43Zr1bQ==",
+ "dependencies": {
+ "System.Composition.Runtime": "8.0.0"
+ }
+ },
+ "System.Composition.Runtime": {
+ "type": "Transitive",
+ "resolved": "8.0.0",
+ "contentHash": "G+kRyB5/6+3ucRRQz+DF4uSHGqpkK8Q4ilVdbt4zvxpmvLVZNmSkyFAQpJLcbOyVF85aomJx0m+TGMDVlwx7ZQ=="
+ },
+ "System.Composition.TypedParts": {
+ "type": "Transitive",
+ "resolved": "8.0.0",
+ "contentHash": "DsSklhuA+Dsgo3ZZrar8hjBFvq1wa1grrkNCTt+6SoX3vq0Vy+HXJnVXrU/nNH1BjlGH684A7h4hJQHZd/u5mA==",
+ "dependencies": {
+ "System.Composition.AttributedModel": "8.0.0",
+ "System.Composition.Hosting": "8.0.0",
+ "System.Composition.Runtime": "8.0.0"
+ }
+ },
+ "System.IO.Pipelines": {
+ "type": "Transitive",
+ "resolved": "8.0.0",
+ "contentHash": "FHNOatmUq0sqJOkTx+UF/9YK1f180cnW5FVqnQMvYUN0elp6wFzbtPSiqbo1/ru8ICp43JM1i7kKkk6GsNGHlA==",
+ "dependencies": {
+ "System.Buffers": "4.5.1",
+ "System.Memory": "4.5.5",
+ "System.Threading.Tasks.Extensions": "4.5.4"
+ }
+ },
+ "System.Memory": {
+ "type": "Transitive",
+ "resolved": "4.5.5",
+ "contentHash": "XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw==",
+ "dependencies": {
+ "System.Buffers": "4.5.1",
+ "System.Numerics.Vectors": "4.4.0",
+ "System.Runtime.CompilerServices.Unsafe": "4.5.3"
+ }
+ },
+ "System.Numerics.Vectors": {
+ "type": "Transitive",
+ "resolved": "4.4.0",
+ "contentHash": "UiLzLW+Lw6HLed1Hcg+8jSRttrbuXv7DANVj0DkL9g6EnnzbL75EB7EWsw5uRbhxd/4YdG8li5XizGWepmG3PQ=="
+ },
+ "System.Reflection.Metadata": {
+ "type": "Transitive",
+ "resolved": "8.0.0",
+ "contentHash": "ptvgrFh7PvWI8bcVqG5rsA/weWM09EnthFHR5SCnS6IN+P4mj6rE1lBDC4U8HL9/57htKAqy4KQ3bBj84cfYyQ==",
+ "dependencies": {
+ "System.Collections.Immutable": "8.0.0",
+ "System.Memory": "4.5.5"
+ }
+ },
+ "System.Runtime.CompilerServices.Unsafe": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg=="
+ },
+ "System.Text.Encoding.CodePages": {
+ "type": "Transitive",
+ "resolved": "8.0.0",
+ "contentHash": "OZIsVplFGaVY90G2SbpgU7EnCoOO5pw1t4ic21dBF3/1omrJFpAGoNAVpPyMVOC90/hvgkGG3VFqR13YgZMQfg==",
+ "dependencies": {
+ "System.Memory": "4.5.5",
+ "System.Runtime.CompilerServices.Unsafe": "6.0.0"
+ }
+ },
+ "System.Text.Encodings.Web": {
+ "type": "Transitive",
+ "resolved": "8.0.0",
+ "contentHash": "yev/k9GHAEGx2Rg3/tU6MQh4HGBXJs70y7j1LaM1i/ER9po+6nnQ6RRqTJn1E7Xu0fbIFK80Nh5EoODxrbxwBQ==",
+ "dependencies": {
+ "System.Buffers": "4.5.1",
+ "System.Memory": "4.5.5",
+ "System.Runtime.CompilerServices.Unsafe": "6.0.0"
+ }
+ },
+ "System.Threading.Channels": {
+ "type": "Transitive",
+ "resolved": "8.0.0",
+ "contentHash": "CMaFr7v+57RW7uZfZkPExsPB6ljwzhjACWW1gfU35Y56rk72B/Wu+sTqxVmGSk4SFUlPc3cjeKND0zktziyjBA==",
+ "dependencies": {
+ "System.Threading.Tasks.Extensions": "4.5.4"
+ }
+ },
+ "System.Threading.Tasks.Extensions": {
+ "type": "Transitive",
+ "resolved": "4.5.4",
+ "contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==",
+ "dependencies": {
+ "System.Runtime.CompilerServices.Unsafe": "4.5.3"
+ }
+ },
+ "questionable.model": {
+ "type": "Project",
+ "dependencies": {
+ "System.Text.Json": "[8.0.3, )"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/QuestPaths/AssemblyQuestLoader.cs b/QuestPaths/AssemblyQuestLoader.cs
index 95faeb46..9601c4dc 100644
--- a/QuestPaths/AssemblyQuestLoader.cs
+++ b/QuestPaths/AssemblyQuestLoader.cs
@@ -1,30 +1,11 @@
-#if RELEASE
-using System;
-using System.IO;
-using System.IO.Compression;
+using System.Collections.Generic;
+using Questionable.Model.V1;
+#if RELEASE
namespace Questionable.QuestPaths;
-public static class AssemblyQuestLoader
+public static partial class AssemblyQuestLoader
{
- public static void LoadQuestsFromEmbeddedResources(Action loadFunction)
- {
- foreach (string resourceName in typeof(AssemblyQuestLoader).Assembly.GetManifestResourceNames())
- {
- if (resourceName.EndsWith(".zip"))
- {
- using ZipArchive zipArchive =
- new ZipArchive(typeof(AssemblyQuestLoader).Assembly.GetManifestResourceStream(resourceName)!);
- foreach (ZipArchiveEntry entry in zipArchive.Entries)
- {
- if (entry.Name.EndsWith(".json"))
- {
- using Stream stream = entry.Open();
- loadFunction(entry.Name, stream);
- }
- }
- }
- }
- }
+ public static IReadOnlyDictionary GetQuests() => Quests;
}
#endif
diff --git a/QuestPaths/QuestPaths.csproj b/QuestPaths/QuestPaths.csproj
index 3ea68608..2a204647 100644
--- a/QuestPaths/QuestPaths.csproj
+++ b/QuestPaths/QuestPaths.csproj
@@ -8,29 +8,22 @@
true
none
$(SolutionDir)=X:\
+ true
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
-
+
+
+
+
+
+
diff --git a/QuestPaths/packages.lock.json b/QuestPaths/packages.lock.json
index f9ae1775..aced35f4 100644
--- a/QuestPaths/packages.lock.json
+++ b/QuestPaths/packages.lock.json
@@ -1,6 +1,105 @@
{
"version": 1,
"dependencies": {
- "net8.0-windows7.0": {}
+ "net8.0-windows7.0": {
+ "Dalamud.Extensions.MicrosoftLogging": {
+ "type": "Transitive",
+ "resolved": "4.0.1",
+ "contentHash": "fMEL2ajtF/30SBBku7vMyG0yye5eHN/A9fgT//1CEjUth/Wz2CYco5Ehye21T8KN1IuAPwoqJuu49rB71j+8ug==",
+ "dependencies": {
+ "Microsoft.Extensions.Logging": "8.0.0"
+ }
+ },
+ "DalamudPackager": {
+ "type": "Transitive",
+ "resolved": "2.1.12",
+ "contentHash": "Sc0PVxvgg4NQjcI8n10/VfUQBAS4O+Fw2pZrAqBdRMbthYGeogzu5+xmIGCGmsEZ/ukMOBuAqiNiB5qA3MRalg=="
+ },
+ "JetBrains.Annotations": {
+ "type": "Transitive",
+ "resolved": "2023.3.0",
+ "contentHash": "PHfnvdBUdGaTVG9bR/GEfxgTwWM0Z97Y6X3710wiljELBISipSfF5okn/vz+C2gfO+ihoEyVPjaJwn8ZalVukA=="
+ },
+ "Microsoft.Extensions.DependencyInjection": {
+ "type": "Transitive",
+ "resolved": "8.0.0",
+ "contentHash": "V8S3bsm50ig6JSyrbcJJ8bW2b9QLGouz+G1miK3UTaOWmMtFwNNNzUf4AleyDWUmTrWMLNnFSLEQtxmxgNQnNQ==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0"
+ }
+ },
+ "Microsoft.Extensions.DependencyInjection.Abstractions": {
+ "type": "Transitive",
+ "resolved": "8.0.0",
+ "contentHash": "cjWrLkJXK0rs4zofsK4bSdg+jhDLTaxrkXu4gS6Y7MAlCvRyNNgwY/lJi5RDlQOnSZweHqoyvgvbdvQsRIW+hg=="
+ },
+ "Microsoft.Extensions.Logging": {
+ "type": "Transitive",
+ "resolved": "8.0.0",
+ "contentHash": "tvRkov9tAJ3xP51LCv3FJ2zINmv1P8Hi8lhhtcKGqM+ImiTCC84uOPEI4z8Cdq2C3o9e+Aa0Gw0rmrsJD77W+w==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection": "8.0.0",
+ "Microsoft.Extensions.Logging.Abstractions": "8.0.0",
+ "Microsoft.Extensions.Options": "8.0.0"
+ }
+ },
+ "Microsoft.Extensions.Logging.Abstractions": {
+ "type": "Transitive",
+ "resolved": "8.0.0",
+ "contentHash": "arDBqTgFCyS0EvRV7O3MZturChstm50OJ0y9bDJvAcmEPJm0FFpFyjU/JLYyStNGGey081DvnQYlncNX5SJJGA==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0"
+ }
+ },
+ "Microsoft.Extensions.Options": {
+ "type": "Transitive",
+ "resolved": "8.0.0",
+ "contentHash": "JOVOfqpnqlVLUzINQ2fox8evY2SKLYJ3BV8QDe/Jyp21u1T7r45x/R/5QdteURMR5r01GxeJSBBUOCOyaNXA3g==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0",
+ "Microsoft.Extensions.Primitives": "8.0.0"
+ }
+ },
+ "Microsoft.Extensions.Primitives": {
+ "type": "Transitive",
+ "resolved": "8.0.0",
+ "contentHash": "bXJEZrW9ny8vjMF1JV253WeLhpEVzFo1lyaZu1vQ4ZxWUlVvknZ/+ftFgVheLubb4eZPSwwxBeqS1JkCOjxd8g=="
+ },
+ "System.Text.Encodings.Web": {
+ "type": "Transitive",
+ "resolved": "8.0.0",
+ "contentHash": "yev/k9GHAEGx2Rg3/tU6MQh4HGBXJs70y7j1LaM1i/ER9po+6nnQ6RRqTJn1E7Xu0fbIFK80Nh5EoODxrbxwBQ=="
+ },
+ "System.Text.Json": {
+ "type": "Transitive",
+ "resolved": "8.0.3",
+ "contentHash": "hpagS9joOwv6efWfrMmV9MjQXpiXZH72PgN067Ysfr6AWMSD1/1hEcvh/U5mUpPLezEWsOJSuVrmqDIVD958iA==",
+ "dependencies": {
+ "System.Text.Encodings.Web": "8.0.0"
+ }
+ },
+ "llib": {
+ "type": "Project"
+ },
+ "questionable": {
+ "type": "Project",
+ "dependencies": {
+ "Dalamud.Extensions.MicrosoftLogging": "[4.0.1, )",
+ "DalamudPackager": "[2.1.12, )",
+ "JetBrains.Annotations": "[2023.3.0, )",
+ "LLib": "[1.0.0, )",
+ "Microsoft.Extensions.DependencyInjection": "[8.0.0, )",
+ "QuestPaths": "[1.0.0, )",
+ "Questionable.Model": "[1.0.0, )",
+ "System.Text.Json": "[8.0.3, )"
+ }
+ },
+ "questionable.model": {
+ "type": "Project",
+ "dependencies": {
+ "System.Text.Json": "[8.0.3, )"
+ }
+ }
+ }
}
}
\ No newline at end of file
diff --git a/Questionable.Model/Questionable.Model.csproj b/Questionable.Model/Questionable.Model.csproj
new file mode 100644
index 00000000..c1fcd0f1
--- /dev/null
+++ b/Questionable.Model/Questionable.Model.csproj
@@ -0,0 +1,15 @@
+
+
+ netstandard2.0
+ 12
+ enable
+ true
+ $(SolutionDir)=X:\
+ true
+ portable
+
+
+
+
+
+
diff --git a/Questionable/Model/V1/AethernetShortcut.cs b/Questionable.Model/V1/AethernetShortcut.cs
similarity index 86%
rename from Questionable/Model/V1/AethernetShortcut.cs
rename to Questionable.Model/V1/AethernetShortcut.cs
index 2fd707a1..40514b58 100644
--- a/Questionable/Model/V1/AethernetShortcut.cs
+++ b/Questionable.Model/V1/AethernetShortcut.cs
@@ -4,7 +4,7 @@ using Questionable.Model.V1.Converter;
namespace Questionable.Model.V1;
[JsonConverter(typeof(AethernetShortcutConverter))]
-internal sealed class AethernetShortcut
+public sealed class AethernetShortcut
{
public EAetheryteLocation From { get; set; }
public EAetheryteLocation To { get; set; }
diff --git a/Questionable.Model/V1/ChatMessage.cs b/Questionable.Model/V1/ChatMessage.cs
new file mode 100644
index 00000000..71721380
--- /dev/null
+++ b/Questionable.Model/V1/ChatMessage.cs
@@ -0,0 +1,7 @@
+namespace Questionable.Model.V1;
+
+public sealed class ChatMessage
+{
+ public string? ExcelSheet { get; set; }
+ public string Key { get; set; } = null!;
+}
diff --git a/Questionable/Model/V1/Converter/AethernetShortcutConverter.cs b/Questionable.Model/V1/Converter/AethernetShortcutConverter.cs
similarity index 98%
rename from Questionable/Model/V1/Converter/AethernetShortcutConverter.cs
rename to Questionable.Model/V1/Converter/AethernetShortcutConverter.cs
index 9393e9c3..76a06550 100644
--- a/Questionable/Model/V1/Converter/AethernetShortcutConverter.cs
+++ b/Questionable.Model/V1/Converter/AethernetShortcutConverter.cs
@@ -6,7 +6,7 @@ using System.Text.Json.Serialization;
namespace Questionable.Model.V1.Converter;
-internal sealed class AethernetShortcutConverter : JsonConverter
+public sealed class AethernetShortcutConverter : JsonConverter
{
private static readonly Dictionary EnumToString = new()
{
@@ -151,9 +151,6 @@ internal sealed class AethernetShortcutConverter : JsonConverter(Values)
+public sealed class AetheryteConverter() : EnumConverter(Values)
{
private static readonly Dictionary Values = new()
{
diff --git a/Questionable/Model/V1/Converter/DialogueChoiceTypeConverter.cs b/Questionable.Model/V1/Converter/DialogueChoiceTypeConverter.cs
similarity index 73%
rename from Questionable/Model/V1/Converter/DialogueChoiceTypeConverter.cs
rename to Questionable.Model/V1/Converter/DialogueChoiceTypeConverter.cs
index b40304d7..ea832cac 100644
--- a/Questionable/Model/V1/Converter/DialogueChoiceTypeConverter.cs
+++ b/Questionable.Model/V1/Converter/DialogueChoiceTypeConverter.cs
@@ -2,7 +2,7 @@
namespace Questionable.Model.V1.Converter;
-internal sealed class DialogueChoiceTypeConverter() : EnumConverter(Values)
+public sealed class DialogueChoiceTypeConverter() : EnumConverter(Values)
{
private static readonly Dictionary Values = new()
{
diff --git a/Questionable/Model/V1/Converter/EmoteConverter.cs b/Questionable.Model/V1/Converter/EmoteConverter.cs
similarity index 86%
rename from Questionable/Model/V1/Converter/EmoteConverter.cs
rename to Questionable.Model/V1/Converter/EmoteConverter.cs
index bf8e62de..8cc50027 100644
--- a/Questionable/Model/V1/Converter/EmoteConverter.cs
+++ b/Questionable.Model/V1/Converter/EmoteConverter.cs
@@ -2,7 +2,7 @@
namespace Questionable.Model.V1.Converter;
-internal sealed class EmoteConverter() : EnumConverter(Values)
+public sealed class EmoteConverter() : EnumConverter(Values)
{
private static readonly Dictionary Values = new()
{
diff --git a/Questionable/Model/V1/Converter/EnemySpawnTypeConverter.cs b/Questionable.Model/V1/Converter/EnemySpawnTypeConverter.cs
similarity index 82%
rename from Questionable/Model/V1/Converter/EnemySpawnTypeConverter.cs
rename to Questionable.Model/V1/Converter/EnemySpawnTypeConverter.cs
index a0ffe843..5c5de532 100644
--- a/Questionable/Model/V1/Converter/EnemySpawnTypeConverter.cs
+++ b/Questionable.Model/V1/Converter/EnemySpawnTypeConverter.cs
@@ -2,7 +2,7 @@
namespace Questionable.Model.V1.Converter;
-internal sealed class EnemySpawnTypeConverter() : EnumConverter(Values)
+public sealed class EnemySpawnTypeConverter() : EnumConverter(Values)
{
private static readonly Dictionary Values = new()
{
diff --git a/Questionable/Model/V1/Converter/EnumConverter.cs b/Questionable.Model/V1/Converter/EnumConverter.cs
similarity index 79%
rename from Questionable/Model/V1/Converter/EnumConverter.cs
rename to Questionable.Model/V1/Converter/EnumConverter.cs
index afd37fde..3ed1267b 100644
--- a/Questionable/Model/V1/Converter/EnumConverter.cs
+++ b/Questionable.Model/V1/Converter/EnumConverter.cs
@@ -7,7 +7,7 @@ using System.Text.Json.Serialization;
namespace Questionable.Model.V1.Converter;
-internal abstract class EnumConverter : JsonConverter
+public abstract class EnumConverter : JsonConverter
where T : Enum
{
private readonly ReadOnlyDictionary _enumToString;
@@ -17,9 +17,8 @@ internal abstract class EnumConverter : JsonConverter
{
_enumToString = values is IDictionary dict
? new ReadOnlyDictionary(dict)
- : values.ToDictionary(x => x.Key, x => x.Value).AsReadOnly();
- _stringToEnum = _enumToString.ToDictionary(x => x.Value, x => x.Key)
- .AsReadOnly();
+ : new ReadOnlyDictionary(values.ToDictionary(x => x.Key, x => x.Value));
+ _stringToEnum = new ReadOnlyDictionary(_enumToString.ToDictionary(x => x.Value, x => x.Key));
}
public override T? Read(ref Utf8JsonReader reader, Type typeToConvert,
@@ -37,7 +36,6 @@ internal abstract class EnumConverter : JsonConverter
public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
{
- ArgumentNullException.ThrowIfNull(writer);
writer.WriteStringValue(_enumToString[value]);
}
}
diff --git a/Questionable/Model/V1/Converter/ExcelRefConverter.cs b/Questionable.Model/V1/Converter/ExcelRefConverter.cs
similarity index 93%
rename from Questionable/Model/V1/Converter/ExcelRefConverter.cs
rename to Questionable.Model/V1/Converter/ExcelRefConverter.cs
index 0c446e4e..0c48e5bb 100644
--- a/Questionable/Model/V1/Converter/ExcelRefConverter.cs
+++ b/Questionable.Model/V1/Converter/ExcelRefConverter.cs
@@ -4,7 +4,7 @@ using System.Text.Json.Serialization;
namespace Questionable.Model.V1.Converter;
-internal sealed class ExcelRefConverter : JsonConverter
+public sealed class ExcelRefConverter : JsonConverter
{
public override ExcelRef? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
diff --git a/Questionable/Model/V1/Converter/InteractionTypeConverter.cs b/Questionable.Model/V1/Converter/InteractionTypeConverter.cs
similarity index 92%
rename from Questionable/Model/V1/Converter/InteractionTypeConverter.cs
rename to Questionable.Model/V1/Converter/InteractionTypeConverter.cs
index d67435f5..6c43696f 100644
--- a/Questionable/Model/V1/Converter/InteractionTypeConverter.cs
+++ b/Questionable.Model/V1/Converter/InteractionTypeConverter.cs
@@ -2,7 +2,7 @@
namespace Questionable.Model.V1.Converter;
-internal sealed class InteractionTypeConverter() : EnumConverter(Values)
+public sealed class InteractionTypeConverter() : EnumConverter(Values)
{
private static readonly Dictionary Values = new()
{
diff --git a/Questionable/Model/V1/Converter/SkipConditionConverter.cs b/Questionable.Model/V1/Converter/SkipConditionConverter.cs
similarity index 79%
rename from Questionable/Model/V1/Converter/SkipConditionConverter.cs
rename to Questionable.Model/V1/Converter/SkipConditionConverter.cs
index a65d5044..dd38ac4f 100644
--- a/Questionable/Model/V1/Converter/SkipConditionConverter.cs
+++ b/Questionable.Model/V1/Converter/SkipConditionConverter.cs
@@ -2,7 +2,7 @@
namespace Questionable.Model.V1.Converter;
-internal sealed class SkipConditionConverter() : EnumConverter(Values)
+public sealed class SkipConditionConverter() : EnumConverter(Values)
{
private static readonly Dictionary Values = new()
{
diff --git a/Questionable/Model/V1/Converter/VectorConverter.cs b/Questionable.Model/V1/Converter/VectorConverter.cs
similarity index 94%
rename from Questionable/Model/V1/Converter/VectorConverter.cs
rename to Questionable.Model/V1/Converter/VectorConverter.cs
index 575fd885..f75ffe6a 100644
--- a/Questionable/Model/V1/Converter/VectorConverter.cs
+++ b/Questionable.Model/V1/Converter/VectorConverter.cs
@@ -5,7 +5,7 @@ using System.Text.Json.Serialization;
namespace Questionable.Model.V1.Converter;
-internal sealed class VectorConverter : JsonConverter
+public sealed class VectorConverter : JsonConverter
{
public override Vector3 Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
@@ -55,8 +55,6 @@ internal sealed class VectorConverter : JsonConverter
public override void Write(Utf8JsonWriter writer, Vector3 value, JsonSerializerOptions options)
{
- ArgumentNullException.ThrowIfNull(writer);
-
writer.WriteStartObject();
writer.WriteNumber(nameof(Vector3.X), value.X);
writer.WriteNumber(nameof(Vector3.Y), value.X);
diff --git a/Questionable/Model/V1/DialogueChoice.cs b/Questionable.Model/V1/DialogueChoice.cs
similarity index 81%
rename from Questionable/Model/V1/DialogueChoice.cs
rename to Questionable.Model/V1/DialogueChoice.cs
index ddfc0ae0..80b49d05 100644
--- a/Questionable/Model/V1/DialogueChoice.cs
+++ b/Questionable.Model/V1/DialogueChoice.cs
@@ -1,11 +1,9 @@
using System.Text.Json.Serialization;
-using JetBrains.Annotations;
using Questionable.Model.V1.Converter;
namespace Questionable.Model.V1;
-[UsedImplicitly(ImplicitUseKindFlags.Assign, ImplicitUseTargetFlags.WithMembers)]
-internal sealed class DialogueChoice
+public sealed class DialogueChoice
{
[JsonConverter(typeof(DialogueChoiceTypeConverter))]
public EDialogChoiceType Type { get; set; }
diff --git a/Questionable/Model/V1/EAetheryteLocation.cs b/Questionable.Model/V1/EAetheryteLocation.cs
similarity index 99%
rename from Questionable/Model/V1/EAetheryteLocation.cs
rename to Questionable.Model/V1/EAetheryteLocation.cs
index c6ec79f9..a49a471e 100644
--- a/Questionable/Model/V1/EAetheryteLocation.cs
+++ b/Questionable.Model/V1/EAetheryteLocation.cs
@@ -4,7 +4,7 @@ using Questionable.Model.V1.Converter;
namespace Questionable.Model.V1;
[JsonConverter(typeof(AetheryteConverter))]
-internal enum EAetheryteLocation
+public enum EAetheryteLocation
{
None = 0,
diff --git a/Questionable/Model/V1/EDialogChoiceType.cs b/Questionable.Model/V1/EDialogChoiceType.cs
similarity index 69%
rename from Questionable/Model/V1/EDialogChoiceType.cs
rename to Questionable.Model/V1/EDialogChoiceType.cs
index e8f18dda..066639a3 100644
--- a/Questionable/Model/V1/EDialogChoiceType.cs
+++ b/Questionable.Model/V1/EDialogChoiceType.cs
@@ -1,6 +1,6 @@
namespace Questionable.Model.V1;
-internal enum EDialogChoiceType
+public enum EDialogChoiceType
{
None,
YesNo,
diff --git a/Questionable/Model/V1/EEmote.cs b/Questionable.Model/V1/EEmote.cs
similarity index 93%
rename from Questionable/Model/V1/EEmote.cs
rename to Questionable.Model/V1/EEmote.cs
index 2e751d36..3ad0afbb 100644
--- a/Questionable/Model/V1/EEmote.cs
+++ b/Questionable.Model/V1/EEmote.cs
@@ -4,7 +4,7 @@ using Questionable.Model.V1.Converter;
namespace Questionable.Model.V1;
[JsonConverter(typeof(EmoteConverter))]
-internal enum EEmote
+public enum EEmote
{
None = 0,
diff --git a/Questionable/Model/V1/EEnemySpawnType.cs b/Questionable.Model/V1/EEnemySpawnType.cs
similarity index 89%
rename from Questionable/Model/V1/EEnemySpawnType.cs
rename to Questionable.Model/V1/EEnemySpawnType.cs
index 1c19132d..8465f011 100644
--- a/Questionable/Model/V1/EEnemySpawnType.cs
+++ b/Questionable.Model/V1/EEnemySpawnType.cs
@@ -4,7 +4,7 @@ using Questionable.Model.V1.Converter;
namespace Questionable.Model.V1;
[JsonConverter(typeof(EnemySpawnTypeConverter))]
-internal enum EEnemySpawnType
+public enum EEnemySpawnType
{
None = 0,
AfterInteraction,
diff --git a/Questionable/Model/V1/EInteractionType.cs b/Questionable.Model/V1/EInteractionType.cs
similarity index 95%
rename from Questionable/Model/V1/EInteractionType.cs
rename to Questionable.Model/V1/EInteractionType.cs
index edb27cee..6e3b7da8 100644
--- a/Questionable/Model/V1/EInteractionType.cs
+++ b/Questionable.Model/V1/EInteractionType.cs
@@ -4,7 +4,7 @@ using Questionable.Model.V1.Converter;
namespace Questionable.Model.V1;
[JsonConverter(typeof(InteractionTypeConverter))]
-internal enum EInteractionType
+public enum EInteractionType
{
Interact,
WalkTo,
diff --git a/Questionable/Model/V1/ESkipCondition.cs b/Questionable.Model/V1/ESkipCondition.cs
similarity index 88%
rename from Questionable/Model/V1/ESkipCondition.cs
rename to Questionable.Model/V1/ESkipCondition.cs
index f7e173c9..4f2639d4 100644
--- a/Questionable/Model/V1/ESkipCondition.cs
+++ b/Questionable.Model/V1/ESkipCondition.cs
@@ -4,7 +4,7 @@ using Questionable.Model.V1.Converter;
namespace Questionable.Model.V1;
[JsonConverter(typeof(SkipConditionConverter))]
-internal enum ESkipCondition
+public enum ESkipCondition
{
None,
Never,
diff --git a/Questionable/Model/V1/ExcelRef.cs b/Questionable.Model/V1/ExcelRef.cs
similarity index 100%
rename from Questionable/Model/V1/ExcelRef.cs
rename to Questionable.Model/V1/ExcelRef.cs
diff --git a/Questionable/Model/V1/JumpDestination.cs b/Questionable.Model/V1/JumpDestination.cs
similarity index 68%
rename from Questionable/Model/V1/JumpDestination.cs
rename to Questionable.Model/V1/JumpDestination.cs
index 1827f879..e6a709e7 100644
--- a/Questionable/Model/V1/JumpDestination.cs
+++ b/Questionable.Model/V1/JumpDestination.cs
@@ -1,12 +1,10 @@
using System.Numerics;
using System.Text.Json.Serialization;
-using JetBrains.Annotations;
using Questionable.Model.V1.Converter;
namespace Questionable.Model.V1;
-[UsedImplicitly(ImplicitUseKindFlags.Assign, ImplicitUseTargetFlags.WithMembers)]
-internal sealed class JumpDestination
+public sealed class JumpDestination
{
[JsonConverter(typeof(VectorConverter))]
public Vector3 Position { get; set; }
diff --git a/Questionable.Model/V1/QuestData.cs b/Questionable.Model/V1/QuestData.cs
new file mode 100644
index 00000000..111bd257
--- /dev/null
+++ b/Questionable.Model/V1/QuestData.cs
@@ -0,0 +1,12 @@
+using System.Collections.Generic;
+
+namespace Questionable.Model.V1;
+
+public sealed class QuestData
+{
+ public string Author { get; set; } = null!;
+ public List Contributors { get; set; } = new();
+ public string? Comment { get; set; }
+ public List TerritoryBlacklist { get; set; } = new();
+ public List QuestSequence { get; set; } = new();
+}
diff --git a/Questionable/Model/V1/QuestSequence.cs b/Questionable.Model/V1/QuestSequence.cs
similarity index 62%
rename from Questionable/Model/V1/QuestSequence.cs
rename to Questionable.Model/V1/QuestSequence.cs
index 58393c32..62736416 100644
--- a/Questionable/Model/V1/QuestSequence.cs
+++ b/Questionable.Model/V1/QuestSequence.cs
@@ -1,12 +1,10 @@
using System.Collections.Generic;
-using JetBrains.Annotations;
namespace Questionable.Model.V1;
-[UsedImplicitly(ImplicitUseKindFlags.Assign, ImplicitUseTargetFlags.WithMembers)]
-internal sealed class QuestSequence
+public sealed class QuestSequence
{
- public required int Sequence { get; set; }
+ public int Sequence { get; set; }
public string? Comment { get; set; }
public List Steps { get; set; } = new();
diff --git a/Questionable/Model/V1/QuestStep.cs b/Questionable.Model/V1/QuestStep.cs
similarity index 54%
rename from Questionable/Model/V1/QuestStep.cs
rename to Questionable.Model/V1/QuestStep.cs
index 44e3ce44..029060e7 100644
--- a/Questionable/Model/V1/QuestStep.cs
+++ b/Questionable.Model/V1/QuestStep.cs
@@ -3,14 +3,11 @@ using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Numerics;
using System.Text.Json.Serialization;
-using FFXIVClientStructs.FFXIV.Application.Network.WorkDefinitions;
-using JetBrains.Annotations;
using Questionable.Model.V1.Converter;
namespace Questionable.Model.V1;
-[UsedImplicitly(ImplicitUseKindFlags.Assign, ImplicitUseTargetFlags.WithMembers)]
-internal sealed class QuestStep
+public sealed class QuestStep
{
public EInteractionType InteractionType { get; set; }
@@ -42,8 +39,8 @@ internal sealed class QuestStep
public ChatMessage? ChatMessage { get; set; }
public EEnemySpawnType? EnemySpawnType { get; set; }
-
public IList KillEnemyDataIds { get; set; } = new List();
+
public JumpDestination? JumpDestination { get; set; }
public uint? ContentFinderConditionId { get; set; }
@@ -51,37 +48,16 @@ internal sealed class QuestStep
public IList CompletionQuestVariablesFlags { get; set; } = new List();
public IList DialogueChoices { get; set; } = new List();
- ///
- /// Positive values: Must be set to this value; will wait for the step to have these set.
- /// Negative values: Will skip if set to this value, won't wait for this to be set.
- ///
- public unsafe bool MatchesQuestVariables(QuestWork questWork, bool forSkip)
+ [JsonConstructor]
+ public QuestStep()
{
- if (CompletionQuestVariablesFlags.Count != 6)
- return false;
+ }
- for (int i = 0; i < 6; ++i)
- {
- short? check = CompletionQuestVariablesFlags[i];
- if (check == null)
- continue;
-
- byte actualValue = questWork.Variables[i];
- byte checkByte = check > 0 ? (byte)check : (byte)-check;
- if (forSkip)
- {
- byte expectedValue = (byte)Math.Abs(check.Value);
- if ((actualValue & checkByte) != expectedValue)
- return false;
- }
- else if (!forSkip && check > 0)
- {
- byte expectedValue = check > 0 ? (byte)check : (byte)0;
- if ((actualValue & checkByte) != expectedValue)
- return false;
- }
- }
-
- return true;
+ public QuestStep(EInteractionType interactionType, uint? dataId, Vector3? position, ushort territoryId)
+ {
+ InteractionType = interactionType;
+ DataId = dataId;
+ Position = position;
+ TerritoryId = territoryId;
}
}
diff --git a/Questionable.Model/packages.lock.json b/Questionable.Model/packages.lock.json
new file mode 100644
index 00000000..7bcc7e48
--- /dev/null
+++ b/Questionable.Model/packages.lock.json
@@ -0,0 +1,86 @@
+{
+ "version": 1,
+ "dependencies": {
+ ".NETStandard,Version=v2.0": {
+ "NETStandard.Library": {
+ "type": "Direct",
+ "requested": "[2.0.3, )",
+ "resolved": "2.0.3",
+ "contentHash": "st47PosZSHrjECdjeIzZQbzivYBJFv6P2nv4cj2ypdI204DO+vZ7l5raGMiX4eXMJ53RfOIg+/s4DHVZ54Nu2A==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0"
+ }
+ },
+ "System.Text.Json": {
+ "type": "Direct",
+ "requested": "[8.0.3, )",
+ "resolved": "8.0.3",
+ "contentHash": "hpagS9joOwv6efWfrMmV9MjQXpiXZH72PgN067Ysfr6AWMSD1/1hEcvh/U5mUpPLezEWsOJSuVrmqDIVD958iA==",
+ "dependencies": {
+ "Microsoft.Bcl.AsyncInterfaces": "8.0.0",
+ "System.Buffers": "4.5.1",
+ "System.Memory": "4.5.5",
+ "System.Runtime.CompilerServices.Unsafe": "6.0.0",
+ "System.Text.Encodings.Web": "8.0.0",
+ "System.Threading.Tasks.Extensions": "4.5.4"
+ }
+ },
+ "Microsoft.Bcl.AsyncInterfaces": {
+ "type": "Transitive",
+ "resolved": "8.0.0",
+ "contentHash": "3WA9q9yVqJp222P3x1wYIGDAkpjAku0TMUaaQV22g6L67AI0LdOIrVS7Ht2vJfLHGSPVuqN94vIr15qn+HEkHw==",
+ "dependencies": {
+ "System.Threading.Tasks.Extensions": "4.5.4"
+ }
+ },
+ "Microsoft.NETCore.Platforms": {
+ "type": "Transitive",
+ "resolved": "1.1.0",
+ "contentHash": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A=="
+ },
+ "System.Buffers": {
+ "type": "Transitive",
+ "resolved": "4.5.1",
+ "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg=="
+ },
+ "System.Memory": {
+ "type": "Transitive",
+ "resolved": "4.5.5",
+ "contentHash": "XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw==",
+ "dependencies": {
+ "System.Buffers": "4.5.1",
+ "System.Numerics.Vectors": "4.4.0",
+ "System.Runtime.CompilerServices.Unsafe": "4.5.3"
+ }
+ },
+ "System.Numerics.Vectors": {
+ "type": "Transitive",
+ "resolved": "4.4.0",
+ "contentHash": "UiLzLW+Lw6HLed1Hcg+8jSRttrbuXv7DANVj0DkL9g6EnnzbL75EB7EWsw5uRbhxd/4YdG8li5XizGWepmG3PQ=="
+ },
+ "System.Runtime.CompilerServices.Unsafe": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg=="
+ },
+ "System.Text.Encodings.Web": {
+ "type": "Transitive",
+ "resolved": "8.0.0",
+ "contentHash": "yev/k9GHAEGx2Rg3/tU6MQh4HGBXJs70y7j1LaM1i/ER9po+6nnQ6RRqTJn1E7Xu0fbIFK80Nh5EoODxrbxwBQ==",
+ "dependencies": {
+ "System.Buffers": "4.5.1",
+ "System.Memory": "4.5.5",
+ "System.Runtime.CompilerServices.Unsafe": "6.0.0"
+ }
+ },
+ "System.Threading.Tasks.Extensions": {
+ "type": "Transitive",
+ "resolved": "4.5.4",
+ "contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==",
+ "dependencies": {
+ "System.Runtime.CompilerServices.Unsafe": "4.5.3"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Questionable.sln b/Questionable.sln
index 1ad54b6d..5a420a9c 100644
--- a/Questionable.sln
+++ b/Questionable.sln
@@ -6,6 +6,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LLib", "LLib\LLib.csproj",
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "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}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Questionable.Model", "Questionable.Model\Questionable.Model.csproj", "{E15144A5-AFF5-4D86-9561-AFF7DF7F505D}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -24,5 +28,13 @@ Global
{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
EndGlobalSection
EndGlobal
diff --git a/Questionable/.gitignore b/Questionable/.gitignore
index 958518b5..a60a458a 100644
--- a/Questionable/.gitignore
+++ b/Questionable/.gitignore
@@ -1,3 +1 @@
/dist
-/obj
-/bin
diff --git a/Questionable/Controller/QuestRegistry.cs b/Questionable/Controller/QuestRegistry.cs
index 1bc3a44e..71b91a19 100644
--- a/Questionable/Controller/QuestRegistry.cs
+++ b/Questionable/Controller/QuestRegistry.cs
@@ -33,7 +33,17 @@ internal sealed class QuestRegistry
#if RELEASE
_logger.LogInformation("Loading quests from assembly");
- QuestPaths.AssemblyQuestLoader.LoadQuestsFromEmbeddedResources(LoadQuestFromStream);
+
+ foreach ((ushort questId, QuestData questData) in QuestPaths.AssemblyQuestLoader.GetQuests())
+ {
+ Quest quest = new()
+ {
+ QuestId = questId,
+ Name = string.Empty,
+ Data = questData,
+ };
+ _quests[questId] = quest;
+ }
#else
DirectoryInfo? solutionDirectory = _pluginInterface.AssemblyLocation?.Directory?.Parent?.Parent;
if (solutionDirectory != null)
@@ -48,6 +58,7 @@ internal sealed class QuestRegistry
}
}
#endif
+
LoadFromDirectory(new DirectoryInfo(Path.Combine(_pluginInterface.ConfigDirectory.FullName, "Quests")));
foreach (var (questId, quest) in _quests)
@@ -60,6 +71,8 @@ internal sealed class QuestRegistry
quest.Name = questData.Name.ToString();
quest.Level = questData.ClassJobLevel0;
}
+
+ _logger.LogInformation("Loaded {Count} quests", _quests.Count);
}
diff --git a/Questionable/Model/V1/ChatMessage.cs b/Questionable/Model/V1/ChatMessage.cs
deleted file mode 100644
index c33bf43a..00000000
--- a/Questionable/Model/V1/ChatMessage.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-using JetBrains.Annotations;
-
-namespace Questionable.Model.V1;
-
-[UsedImplicitly(ImplicitUseKindFlags.Assign, ImplicitUseTargetFlags.WithMembers)]
-internal sealed class ChatMessage
-{
- public string? ExcelSheet { get; set; }
- public string Key { get; set; } = null!;
-}
diff --git a/Questionable/Model/V1/QuestData.cs b/Questionable/Model/V1/QuestData.cs
deleted file mode 100644
index d484481b..00000000
--- a/Questionable/Model/V1/QuestData.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using System.Collections.Generic;
-using JetBrains.Annotations;
-
-namespace Questionable.Model.V1;
-
-[UsedImplicitly(ImplicitUseKindFlags.Assign, ImplicitUseTargetFlags.WithMembers)]
-internal sealed class QuestData
-{
- public required string Author { get; set; }
- public List Contributors { get; set; } = new();
- public string? Comment { get; set; }
- public List TerritoryBlacklist { get; set; } = new();
- public required List QuestSequence { get; set; } = new();
-}
diff --git a/Questionable/Model/V1/QuestStepExtensions.cs b/Questionable/Model/V1/QuestStepExtensions.cs
new file mode 100644
index 00000000..dedf2ebc
--- /dev/null
+++ b/Questionable/Model/V1/QuestStepExtensions.cs
@@ -0,0 +1,41 @@
+using System;
+using FFXIVClientStructs.FFXIV.Application.Network.WorkDefinitions;
+
+namespace Questionable.Model.V1;
+
+internal static class QuestStepExtensions
+{
+ ///
+ /// Positive values: Must be set to this value; will wait for the step to have these set.
+ /// Negative values: Will skip if set to this value, won't wait for this to be set.
+ ///
+ public static unsafe bool MatchesQuestVariables(this QuestStep step, QuestWork questWork, bool forSkip)
+ {
+ if (step.CompletionQuestVariablesFlags.Count != 6)
+ return false;
+
+ for (int i = 0; i < 6; ++i)
+ {
+ short? check = step.CompletionQuestVariablesFlags[i];
+ if (check == null)
+ continue;
+
+ byte actualValue = questWork.Variables[i];
+ byte checkByte = check > 0 ? (byte)check : (byte)-check;
+ if (forSkip)
+ {
+ byte expectedValue = (byte)Math.Abs(check.Value);
+ if ((actualValue & checkByte) != expectedValue)
+ return false;
+ }
+ else if (!forSkip && check > 0)
+ {
+ byte expectedValue = check > 0 ? (byte)check : (byte)0;
+ if ((actualValue & checkByte) != expectedValue)
+ return false;
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/Questionable/Questionable.csproj b/Questionable/Questionable.csproj
index 2e9031b4..64a7caf1 100644
--- a/Questionable/Questionable.csproj
+++ b/Questionable/Questionable.csproj
@@ -59,6 +59,7 @@
-
+
+
diff --git a/Questionable/packages.lock.json b/Questionable/packages.lock.json
index e4dec3d5..f9ea92b0 100644
--- a/Questionable/packages.lock.json
+++ b/Questionable/packages.lock.json
@@ -86,8 +86,17 @@
"llib": {
"type": "Project"
},
+ "questionable.model": {
+ "type": "Project",
+ "dependencies": {
+ "System.Text.Json": "[8.0.3, )"
+ }
+ },
"questpaths": {
- "type": "Project"
+ "type": "Project",
+ "dependencies": {
+ "Questionable.Model": "[1.0.0, )"
+ }
}
}
}