Schema update
This commit is contained in:
parent
ae87b4ccc5
commit
9bfbc99144
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -1,3 +1,6 @@
|
||||
[submodule "LLib"]
|
||||
path = LLib
|
||||
url = https://git.carvel.li/liza/LLib.git
|
||||
[submodule "vendor/ECommons"]
|
||||
path = vendor/ECommons
|
||||
url = https://github.com/NightmareXIV/ECommons.git
|
||||
|
@ -1,3 +1,8 @@
|
||||
<Project Sdk="Dalamud.NET.Sdk/10.0.0">
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Questionable.Model\Questionable.Model.csproj" />
|
||||
<ProjectReference Include="..\vendor\ECommons\ECommons\ECommons.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="..\LLib\LLib.targets"/>
|
||||
</Project>
|
||||
|
6
GatheringPathRenderer/GatheringPathRenderer.json
Normal file
6
GatheringPathRenderer/GatheringPathRenderer.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"Name": "GatheringPathRenderer",
|
||||
"Author": "Liza Carvelli",
|
||||
"Punchline": "dev only plugin: Renders gathering location.",
|
||||
"Description": "dev only plugin: Renders gathering location (without ECommons polluting the entire normal project)."
|
||||
}
|
@ -1,11 +1,189 @@
|
||||
using Dalamud.Plugin;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Dalamud.Plugin;
|
||||
using Dalamud.Plugin.Services;
|
||||
using ECommons;
|
||||
using ECommons.Schedulers;
|
||||
using ECommons.SplatoonAPI;
|
||||
using Questionable.Model.Gathering;
|
||||
|
||||
namespace GatheringPathRenderer;
|
||||
|
||||
public sealed class RendererPlugin : IDalamudPlugin
|
||||
{
|
||||
private const long OnTerritoryChange = -2;
|
||||
private readonly IDalamudPluginInterface _pluginInterface;
|
||||
private readonly IClientState _clientState;
|
||||
private readonly IPluginLog _pluginLog;
|
||||
private readonly List<(ushort Id, GatheringRoot Root)> _gatheringLocations = [];
|
||||
|
||||
public RendererPlugin(IDalamudPluginInterface pluginInterface, IClientState clientState, IPluginLog pluginLog)
|
||||
{
|
||||
_pluginInterface = pluginInterface;
|
||||
_clientState = clientState;
|
||||
_pluginLog = pluginLog;
|
||||
|
||||
_pluginInterface.GetIpcSubscriber<object>("Questionable.ReloadData")
|
||||
.Subscribe(Reload);
|
||||
|
||||
ECommonsMain.Init(pluginInterface, this, Module.SplatoonAPI);
|
||||
LoadGatheringLocationsFromDirectory();
|
||||
|
||||
_clientState.TerritoryChanged += TerritoryChanged;
|
||||
if (_clientState.IsLoggedIn)
|
||||
TerritoryChanged(_clientState.TerritoryType);
|
||||
}
|
||||
|
||||
private void Reload()
|
||||
{
|
||||
LoadGatheringLocationsFromDirectory();
|
||||
TerritoryChanged(_clientState.TerritoryType);
|
||||
}
|
||||
|
||||
private void LoadGatheringLocationsFromDirectory()
|
||||
{
|
||||
_gatheringLocations.Clear();
|
||||
|
||||
DirectoryInfo? solutionDirectory = _pluginInterface.AssemblyLocation.Directory?.Parent?.Parent?.Parent;
|
||||
if (solutionDirectory != null)
|
||||
{
|
||||
DirectoryInfo pathProjectDirectory =
|
||||
new DirectoryInfo(Path.Combine(solutionDirectory.FullName, "GatheringPaths"));
|
||||
if (pathProjectDirectory.Exists)
|
||||
{
|
||||
try
|
||||
{
|
||||
LoadFromDirectory(
|
||||
new DirectoryInfo(Path.Combine(pathProjectDirectory.FullName, "2.x - A Realm Reborn")));
|
||||
LoadFromDirectory(
|
||||
new DirectoryInfo(Path.Combine(pathProjectDirectory.FullName, "3.x - Heavensward")));
|
||||
LoadFromDirectory(
|
||||
new DirectoryInfo(Path.Combine(pathProjectDirectory.FullName, "4.x - Stormblood")));
|
||||
LoadFromDirectory(
|
||||
new DirectoryInfo(Path.Combine(pathProjectDirectory.FullName, "5.x - Shadowbringers")));
|
||||
LoadFromDirectory(
|
||||
new DirectoryInfo(Path.Combine(pathProjectDirectory.FullName, "6.x - Endwalker")));
|
||||
LoadFromDirectory(
|
||||
new DirectoryInfo(Path.Combine(pathProjectDirectory.FullName, "7.x - Dawntrail")));
|
||||
|
||||
_pluginLog.Information(
|
||||
$"Loaded {_gatheringLocations.Count} gathering root locations from project directory");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_pluginLog.Error(e, "Failed to load quests from project directory");
|
||||
}
|
||||
}
|
||||
else
|
||||
_pluginLog.Warning($"Project directory {pathProjectDirectory} does not exist");
|
||||
}
|
||||
else
|
||||
_pluginLog.Warning($"Solution directory {solutionDirectory} does not exist");
|
||||
}
|
||||
|
||||
private void LoadFromDirectory(DirectoryInfo directory)
|
||||
{
|
||||
if (!directory.Exists)
|
||||
return;
|
||||
|
||||
_pluginLog.Information($"Loading locations from {directory}");
|
||||
foreach (FileInfo fileInfo in directory.GetFiles("*.json"))
|
||||
{
|
||||
try
|
||||
{
|
||||
using FileStream stream = new FileStream(fileInfo.FullName, FileMode.Open, FileAccess.Read);
|
||||
LoadLocationFromStream(fileInfo.Name, stream);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new InvalidDataException($"Unable to load file {fileInfo.FullName}", e);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (DirectoryInfo childDirectory in directory.GetDirectories())
|
||||
LoadFromDirectory(childDirectory);
|
||||
}
|
||||
|
||||
private void LoadLocationFromStream(string fileName, Stream stream)
|
||||
{
|
||||
var locationNode = JsonNode.Parse(stream)!;
|
||||
GatheringRoot root = locationNode.Deserialize<GatheringRoot>()!;
|
||||
_gatheringLocations.Add((ushort.Parse(fileName.Split('_')[0]), root));
|
||||
}
|
||||
|
||||
private void TerritoryChanged(ushort territoryId)
|
||||
{
|
||||
Splatoon.RemoveDynamicElements("GatheringPathRenderer");
|
||||
|
||||
var elements = _gatheringLocations
|
||||
.Where(x => x.Root.TerritoryId == territoryId)
|
||||
.SelectMany(v =>
|
||||
v.Root.Groups.SelectMany(group =>
|
||||
group.Nodes.SelectMany(node => node.Locations
|
||||
.SelectMany(x =>
|
||||
new List<Element>
|
||||
{
|
||||
new Element(x.IsCone()
|
||||
? ElementType.ConeAtFixedCoordinates
|
||||
: ElementType.CircleAtFixedCoordinates)
|
||||
{
|
||||
refX = x.Position.X,
|
||||
refY = x.Position.Z,
|
||||
refZ = x.Position.Y,
|
||||
Filled = true,
|
||||
radius = x.MinimumDistance,
|
||||
Donut = x.MaximumDistance - x.MinimumDistance,
|
||||
color = 0x2020FF80,
|
||||
Enabled = true,
|
||||
coneAngleMin = x.IsCone() ? (int)x.MinimumAngle.GetValueOrDefault() : 0,
|
||||
coneAngleMax = x.IsCone() ? (int)x.MaximumAngle.GetValueOrDefault() : 0
|
||||
},
|
||||
new Element(ElementType.CircleAtFixedCoordinates)
|
||||
{
|
||||
refX = x.Position.X,
|
||||
refY = x.Position.Z,
|
||||
refZ = x.Position.Y,
|
||||
color = 0x00000000,
|
||||
Enabled = true,
|
||||
overlayText = $"{v.Id} // {node.DataId} / {node.Locations.IndexOf(x)}"
|
||||
}
|
||||
}))))
|
||||
.ToList();
|
||||
|
||||
if (elements.Count == 0)
|
||||
{
|
||||
_pluginLog.Information("No new elements to render.");
|
||||
return;
|
||||
}
|
||||
|
||||
_ = new TickScheduler(delegate
|
||||
{
|
||||
try
|
||||
{
|
||||
Splatoon.AddDynamicElements("GatheringPathRenderer",
|
||||
elements.ToArray(),
|
||||
new[] { OnTerritoryChange });
|
||||
_pluginLog.Information($"Created {elements.Count} splatoon elements.");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_pluginLog.Error(e, "Unable to create splatoon layer");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_clientState.TerritoryChanged -= TerritoryChanged;
|
||||
|
||||
Splatoon.RemoveDynamicElements("GatheringPathRenderer");
|
||||
ECommonsMain.Dispose();
|
||||
|
||||
_pluginInterface.GetIpcSubscriber<object>("Questionable.ReloadData")
|
||||
.Unsubscribe(Reload);
|
||||
}
|
||||
}
|
||||
|
@ -75,6 +75,34 @@
|
||||
"Microsoft.Build.Tasks.Git": "1.1.1",
|
||||
"Microsoft.SourceLink.Common": "1.1.1"
|
||||
}
|
||||
},
|
||||
"System.Text.Encodings.Web": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "yev/k9GHAEGx2Rg3/tU6MQh4HGBXJs70y7j1LaM1i/ER9po+6nnQ6RRqTJn1E7Xu0fbIFK80Nh5EoODxrbxwBQ=="
|
||||
},
|
||||
"System.Text.Json": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.4",
|
||||
"contentHash": "bAkhgDJ88XTsqczoxEMliSrpijKZHhbJQldhAmObj/RbrN3sU5dcokuXmWJWsdQAhiMJ9bTayWsL1C9fbbCRhw==",
|
||||
"dependencies": {
|
||||
"System.Text.Encodings.Web": "8.0.0"
|
||||
}
|
||||
},
|
||||
"ecommons": {
|
||||
"type": "Project"
|
||||
},
|
||||
"gatheringpaths": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Questionable.Model": "[1.0.0, )"
|
||||
}
|
||||
},
|
||||
"questionable.model": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"System.Text.Json": "[8.0.4, )"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,54 +3,148 @@
|
||||
"Author": "liza",
|
||||
"TerritoryId": 957,
|
||||
"AetheryteShortcut": "Thavnair - Great Work",
|
||||
"Nodes": [
|
||||
"Groups": [
|
||||
{
|
||||
"DataId": 33918,
|
||||
"Position": {
|
||||
"X": -582.5132,
|
||||
"Y": 40.54578,
|
||||
"Z": -426.0171
|
||||
}
|
||||
"Nodes": [
|
||||
{
|
||||
"DataId": 33918,
|
||||
"Locations": [
|
||||
{
|
||||
"Position": {
|
||||
"X": -582.5132,
|
||||
"Y": 40.54578,
|
||||
"Z": -426.0171
|
||||
},
|
||||
"MinimumAngle": -50,
|
||||
"MaximumAngle": 90
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"DataId": 33919,
|
||||
"Locations": [
|
||||
{
|
||||
"Position": {
|
||||
"X": -578.2101,
|
||||
"Y": 41.27147,
|
||||
"Z": -447.6376
|
||||
},
|
||||
"MinimumAngle": 130,
|
||||
"MaximumAngle": 220
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"X": -546.2882,
|
||||
"Y": 44.52267,
|
||||
"Z": -435.8184
|
||||
},
|
||||
"MinimumAngle": 200,
|
||||
"MaximumAngle": 360
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"DataId": 33919,
|
||||
"Position": {
|
||||
"X": -578.2101,
|
||||
"Y": 41.27147,
|
||||
"Z": -447.6376
|
||||
}
|
||||
"Nodes": [
|
||||
{
|
||||
"DataId": 33920,
|
||||
"Locations": [
|
||||
{
|
||||
"Position": {
|
||||
"X": -488.2276,
|
||||
"Y": 34.71221,
|
||||
"Z": -359.6945
|
||||
},
|
||||
"MinimumAngle": 20,
|
||||
"MaximumAngle": 128,
|
||||
"MinimumDistance": 1.3
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"DataId": 33921,
|
||||
"Locations": [
|
||||
{
|
||||
"Position": {
|
||||
"X": -498.8687,
|
||||
"Y": 31.08014,
|
||||
"Z": -351.9397
|
||||
},
|
||||
"MinimumAngle": 40,
|
||||
"MaximumAngle": 190
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"X": -490.7759,
|
||||
"Y": 28.70215,
|
||||
"Z": -344.4114
|
||||
},
|
||||
"MinimumAngle": -110,
|
||||
"MaximumAngle": 60
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"X": -494.1286,
|
||||
"Y": 32.89971,
|
||||
"Z": -355.0208
|
||||
},
|
||||
"MinimumAngle": 80,
|
||||
"MaximumAngle": 230
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"DataId": 33920,
|
||||
"Position": {
|
||||
"X": -488.2276,
|
||||
"Y": 34.71221,
|
||||
"Z": -359.6945
|
||||
}
|
||||
},
|
||||
{
|
||||
"DataId": 33921,
|
||||
"Position": {
|
||||
"X": -498.8687,
|
||||
"Y": 31.08014,
|
||||
"Z": -351.9397
|
||||
}
|
||||
},
|
||||
{
|
||||
"DataId": 33922,
|
||||
"Position": {
|
||||
"X": -304.0609,
|
||||
"Y": 68.76999,
|
||||
"Z": -479.1875
|
||||
}
|
||||
},
|
||||
{
|
||||
"DataId": 33923,
|
||||
"Position": {
|
||||
"X": -293.6989,
|
||||
"Y": 68.77935,
|
||||
"Z": -484.2256
|
||||
}
|
||||
"Nodes": [
|
||||
{
|
||||
"DataId": 33922,
|
||||
"Locations": [
|
||||
{
|
||||
"Position": {
|
||||
"X": -304.0609,
|
||||
"Y": 68.76999,
|
||||
"Z": -479.1875
|
||||
},
|
||||
"MinimumAngle": -110,
|
||||
"MaximumAngle": 70
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"DataId": 33923,
|
||||
"Locations": [
|
||||
{
|
||||
"Position": {
|
||||
"X": -293.6989,
|
||||
"Y": 68.77935,
|
||||
"Z": -484.2256
|
||||
},
|
||||
"MinimumAngle": -30,
|
||||
"MaximumAngle": 110
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"X": -295.0806,
|
||||
"Y": 69.12621,
|
||||
"Z": -498.1898
|
||||
},
|
||||
"MinimumAngle": 10,
|
||||
"MaximumAngle": 200
|
||||
},
|
||||
{
|
||||
"Position": {
|
||||
"X": -281.4858,
|
||||
"Y": 67.64153,
|
||||
"Z": -477.6673
|
||||
},
|
||||
"MinimumAngle": -90,
|
||||
"MaximumAngle": 60
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -16,12 +16,10 @@ public static partial class AssemblyGatheringLocationLoader
|
||||
if (_locations == null)
|
||||
{
|
||||
_locations = [];
|
||||
#if RELEASE
|
||||
LoadLocations();
|
||||
#endif
|
||||
}
|
||||
|
||||
return _locations ?? throw new InvalidOperationException("quest data is not initialized");
|
||||
return _locations ?? throw new InvalidOperationException("location data is not initialized");
|
||||
}
|
||||
|
||||
public static Stream QuestSchema =>
|
||||
|
@ -26,7 +26,7 @@
|
||||
<AdditionalFiles Include="..\Questionable.Model\common-schema.json" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(Configuration)' == 'Release'">
|
||||
<ItemGroup>
|
||||
<None Remove="2.x - A Realm Reborn" />
|
||||
<None Remove="3.x - Heavensward" />
|
||||
<None Remove="4.x - Stormblood" />
|
||||
|
@ -25,41 +25,64 @@
|
||||
"AetheryteShortcut": {
|
||||
"$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/Aetheryte"
|
||||
},
|
||||
"Nodes": {
|
||||
"Groups": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"DataId": {
|
||||
"type": "number",
|
||||
"minimum": 30000,
|
||||
"maximum": 50000
|
||||
},
|
||||
"Position": {
|
||||
"$ref": "#/$defs/Vector3"
|
||||
},
|
||||
"MinimumAngle": {
|
||||
"type": "number",
|
||||
"minimum": -360,
|
||||
"maximum": 360
|
||||
},
|
||||
"MaximumAngle": {
|
||||
"type": "number",
|
||||
"minimum": -360,
|
||||
"maximum": 360
|
||||
},
|
||||
"MinimumDistance": {
|
||||
"type": "number",
|
||||
"minimum": 0
|
||||
},
|
||||
"MaximumDistance": {
|
||||
"type": "number",
|
||||
"exclusiveMinimum": 0
|
||||
"Nodes": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"DataId": {
|
||||
"type": "number",
|
||||
"minimum": 30000,
|
||||
"maximum": 50000
|
||||
},
|
||||
"Locations": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"Position": {
|
||||
"$ref": "#/$defs/Vector3"
|
||||
},
|
||||
"MinimumAngle": {
|
||||
"type": "number",
|
||||
"minimum": -360,
|
||||
"maximum": 360
|
||||
},
|
||||
"MaximumAngle": {
|
||||
"type": "number",
|
||||
"minimum": -360,
|
||||
"maximum": 360
|
||||
},
|
||||
"MinimumDistance": {
|
||||
"type": "number",
|
||||
"minimum": 0
|
||||
},
|
||||
"MaximumDistance": {
|
||||
"type": "number",
|
||||
"exclusiveMinimum": 0
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"Position"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"DataId"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"DataId",
|
||||
"Position"
|
||||
"Nodes"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
|
@ -153,7 +153,7 @@ public class GatheringSourceGenerator : ISourceGenerator
|
||||
Assignment(nameof(GatheringRoot.TerritoryId), root.TerritoryId, default)
|
||||
.AsSyntaxNodeOrToken(),
|
||||
Assignment(nameof(GatheringRoot.AetheryteShortcut), root.AetheryteShortcut, null),
|
||||
AssignmentList(nameof(GatheringRoot.Nodes), root.Nodes).AsSyntaxNodeOrToken()))));
|
||||
AssignmentList(nameof(GatheringRoot.Groups), root.Groups).AsSyntaxNodeOrToken()))));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -314,30 +314,55 @@ public static class RoslynShortcuts
|
||||
Assignment(nameof(SkipAetheryteCondition.InSameTerritory),
|
||||
skipAetheryteCondition.InSameTerritory, emptyAetheryte.InSameTerritory)))));
|
||||
}
|
||||
else if (value is GatheringNodeLocation nodeLocation)
|
||||
else if (value is GatheringNodeGroup nodeGroup)
|
||||
{
|
||||
var emptyLocation = new GatheringNodeLocation();
|
||||
return ObjectCreationExpression(
|
||||
IdentifierName(nameof(GatheringNodeLocation)))
|
||||
IdentifierName(nameof(GatheringNodeGroup)))
|
||||
.WithInitializer(
|
||||
InitializerExpression(
|
||||
SyntaxKind.ObjectInitializerExpression,
|
||||
SeparatedList<ExpressionSyntax>(
|
||||
SyntaxNodeList(
|
||||
Assignment(nameof(GatheringNodeLocation.DataId), nodeLocation.DataId,
|
||||
AssignmentList(nameof(GatheringNodeGroup.Nodes), nodeGroup.Nodes)
|
||||
.AsSyntaxNodeOrToken()))));
|
||||
}
|
||||
else if (value is GatheringNode nodeLocation)
|
||||
{
|
||||
var emptyLocation = new GatheringNode();
|
||||
return ObjectCreationExpression(
|
||||
IdentifierName(nameof(GatheringNode)))
|
||||
.WithInitializer(
|
||||
InitializerExpression(
|
||||
SyntaxKind.ObjectInitializerExpression,
|
||||
SeparatedList<ExpressionSyntax>(
|
||||
SyntaxNodeList(
|
||||
Assignment(nameof(GatheringNode.DataId), nodeLocation.DataId,
|
||||
emptyLocation.DataId)
|
||||
.AsSyntaxNodeOrToken(),
|
||||
Assignment(nameof(GatheringNodeLocation.Position), nodeLocation.Position,
|
||||
AssignmentList(nameof(GatheringNode.Locations), nodeLocation.Locations)
|
||||
.AsSyntaxNodeOrToken()))));
|
||||
}
|
||||
else if (value is GatheringLocation location)
|
||||
{
|
||||
var emptyLocation = new GatheringLocation();
|
||||
return ObjectCreationExpression(
|
||||
IdentifierName(nameof(GatheringLocation)))
|
||||
.WithInitializer(
|
||||
InitializerExpression(
|
||||
SyntaxKind.ObjectInitializerExpression,
|
||||
SeparatedList<ExpressionSyntax>(
|
||||
SyntaxNodeList(
|
||||
Assignment(nameof(GatheringLocation.Position), location.Position,
|
||||
emptyLocation.Position).AsSyntaxNodeOrToken(),
|
||||
Assignment(nameof(GatheringNodeLocation.MinimumAngle), nodeLocation.MinimumAngle,
|
||||
Assignment(nameof(GatheringLocation.MinimumAngle), location.MinimumAngle,
|
||||
emptyLocation.MinimumAngle).AsSyntaxNodeOrToken(),
|
||||
Assignment(nameof(GatheringNodeLocation.MaximumAngle), nodeLocation.MaximumAngle,
|
||||
Assignment(nameof(GatheringLocation.MaximumAngle), location.MaximumAngle,
|
||||
emptyLocation.MaximumAngle).AsSyntaxNodeOrToken(),
|
||||
Assignment(nameof(GatheringNodeLocation.MinimumDistance),
|
||||
nodeLocation.MinimumDistance, emptyLocation.MinimumDistance)
|
||||
Assignment(nameof(GatheringLocation.MinimumDistance),
|
||||
location.MinimumDistance, emptyLocation.MinimumDistance)
|
||||
.AsSyntaxNodeOrToken(),
|
||||
Assignment(nameof(GatheringNodeLocation.MaximumDistance),
|
||||
nodeLocation.MaximumDistance, emptyLocation.MaximumDistance)
|
||||
Assignment(nameof(GatheringLocation.MaximumDistance),
|
||||
location.MaximumDistance, emptyLocation.MaximumDistance)
|
||||
.AsSyntaxNodeOrToken()))));
|
||||
}
|
||||
else if (value is null)
|
||||
|
@ -55,12 +55,13 @@ public static class Utils
|
||||
Culture = CultureInfo.InvariantCulture,
|
||||
OutputFormat = OutputFormat.List,
|
||||
});
|
||||
if (!evaluationResult.IsValid)
|
||||
if (evaluationResult.HasErrors)
|
||||
{
|
||||
var error = Diagnostic.Create(invalidJson,
|
||||
null,
|
||||
Path.GetFileName(additionalFile.Path));
|
||||
context.ReportDiagnostic(error);
|
||||
continue;
|
||||
}
|
||||
|
||||
yield return (id, node);
|
||||
|
21
Questionable.Model/Gathering/GatheringLocation.cs
Normal file
21
Questionable.Model/Gathering/GatheringLocation.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using System.Numerics;
|
||||
using System.Text.Json.Serialization;
|
||||
using Questionable.Model.Common.Converter;
|
||||
|
||||
namespace Questionable.Model.Gathering;
|
||||
|
||||
public sealed class GatheringLocation
|
||||
{
|
||||
[JsonConverter(typeof(VectorConverter))]
|
||||
public Vector3 Position { get; set; }
|
||||
|
||||
public float? MinimumAngle { get; set; }
|
||||
public float? MaximumAngle { get; set; }
|
||||
public float MinimumDistance { get; set; } = 1f;
|
||||
public float MaximumDistance { get; set; } = 3f;
|
||||
|
||||
public bool IsCone()
|
||||
{
|
||||
return MinimumAngle != null && MaximumAngle != null;
|
||||
}
|
||||
}
|
10
Questionable.Model/Gathering/GatheringNode.cs
Normal file
10
Questionable.Model/Gathering/GatheringNode.cs
Normal file
@ -0,0 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Questionable.Model.Gathering;
|
||||
|
||||
public sealed class GatheringNode
|
||||
{
|
||||
public uint DataId { get; set; }
|
||||
|
||||
public List<GatheringLocation> Locations { get; set; } = [];
|
||||
}
|
8
Questionable.Model/Gathering/GatheringNodeGroup.cs
Normal file
8
Questionable.Model/Gathering/GatheringNodeGroup.cs
Normal file
@ -0,0 +1,8 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Questionable.Model.Gathering;
|
||||
|
||||
public sealed class GatheringNodeGroup
|
||||
{
|
||||
public List<GatheringNode> Nodes { get; set; } = [];
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
using System.Numerics;
|
||||
|
||||
namespace Questionable.Model.Gathering;
|
||||
|
||||
public sealed class GatheringNodeLocation
|
||||
{
|
||||
public uint DataId { get; set; }
|
||||
public Vector3 Position { get; set; }
|
||||
public float? MinimumAngle { get; set; }
|
||||
public float? MaximumAngle { get; set; }
|
||||
public float? MinimumDistance { get; set; } = 0.5f;
|
||||
public float? MaximumDistance { get; set; } = 3f;
|
||||
}
|
@ -14,5 +14,5 @@ public sealed class GatheringRoot
|
||||
[JsonConverter(typeof(AetheryteConverter))]
|
||||
public EAetheryteLocation? AetheryteShortcut { get; set; }
|
||||
|
||||
public List<GatheringNodeLocation> Nodes { get; set; } = [];
|
||||
public List<GatheringNodeGroup> Groups { get; set; } = [];
|
||||
}
|
||||
|
@ -19,6 +19,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GatheringPaths", "Gathering
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GatheringPathRenderer", "GatheringPathRenderer\GatheringPathRenderer.csproj", "{F514DA95-9867-4F3F-8062-ACE0C62E8740}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ECommons", "vendor\ECommons\ECommons\ECommons.csproj", "{A12D7B4B-8E6E-4DCF-A41A-12F62E9FF94B}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
@ -57,6 +59,10 @@ Global
|
||||
{F514DA95-9867-4F3F-8062-ACE0C62E8740}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{F514DA95-9867-4F3F-8062-ACE0C62E8740}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{F514DA95-9867-4F3F-8062-ACE0C62E8740}.Release|x64.Build.0 = Release|Any CPU
|
||||
{A12D7B4B-8E6E-4DCF-A41A-12F62E9FF94B}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{A12D7B4B-8E6E-4DCF-A41A-12F62E9FF94B}.Debug|x64.Build.0 = Debug|x64
|
||||
{A12D7B4B-8E6E-4DCF-A41A-12F62E9FF94B}.Release|x64.ActiveCfg = Release|x64
|
||||
{A12D7B4B-8E6E-4DCF-A41A-12F62E9FF94B}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -8,6 +8,7 @@ using System.Linq;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Dalamud.Plugin;
|
||||
using Dalamud.Plugin.Ipc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Questionable.Data;
|
||||
using Questionable.Model;
|
||||
@ -23,8 +24,9 @@ internal sealed class QuestRegistry
|
||||
private readonly IDalamudPluginInterface _pluginInterface;
|
||||
private readonly QuestData _questData;
|
||||
private readonly QuestValidator _questValidator;
|
||||
private readonly ILogger<QuestRegistry> _logger;
|
||||
private readonly JsonSchemaValidator _jsonSchemaValidator;
|
||||
private readonly ILogger<QuestRegistry> _logger;
|
||||
private readonly ICallGateProvider<object> _reloadDataIpc;
|
||||
|
||||
private readonly Dictionary<ushort, Quest> _quests = new();
|
||||
|
||||
@ -37,6 +39,7 @@ internal sealed class QuestRegistry
|
||||
_questValidator = questValidator;
|
||||
_jsonSchemaValidator = jsonSchemaValidator;
|
||||
_logger = logger;
|
||||
_reloadDataIpc = _pluginInterface.GetIpcProvider<object>("Questionable.ReloadData");
|
||||
}
|
||||
|
||||
public IEnumerable<Quest> AllQuests => _quests.Values;
|
||||
@ -66,6 +69,7 @@ internal sealed class QuestRegistry
|
||||
|
||||
ValidateQuests();
|
||||
Reloaded?.Invoke(this, EventArgs.Empty);
|
||||
_reloadDataIpc.SendMessage();
|
||||
_logger.LogInformation("Loaded {Count} quests in total", _quests.Count);
|
||||
}
|
||||
|
||||
|
1
vendor/ECommons
vendored
Submodule
1
vendor/ECommons
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 9e90d0032f0efd4c9e65d9c5a8e8bd0e99557d68
|
Loading…
Reference in New Issue
Block a user