Schema update
This commit is contained in:
parent
ae87b4ccc5
commit
9bfbc99144
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -1,3 +1,6 @@
|
|||||||
[submodule "LLib"]
|
[submodule "LLib"]
|
||||||
path = LLib
|
path = LLib
|
||||||
url = https://git.carvel.li/liza/LLib.git
|
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">
|
<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"/>
|
<Import Project="..\LLib\LLib.targets"/>
|
||||||
</Project>
|
</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;
|
namespace GatheringPathRenderer;
|
||||||
|
|
||||||
public sealed class RendererPlugin : IDalamudPlugin
|
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()
|
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.Build.Tasks.Git": "1.1.1",
|
||||||
"Microsoft.SourceLink.Common": "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",
|
"Author": "liza",
|
||||||
"TerritoryId": 957,
|
"TerritoryId": 957,
|
||||||
"AetheryteShortcut": "Thavnair - Great Work",
|
"AetheryteShortcut": "Thavnair - Great Work",
|
||||||
"Nodes": [
|
"Groups": [
|
||||||
{
|
{
|
||||||
"DataId": 33918,
|
"Nodes": [
|
||||||
"Position": {
|
{
|
||||||
"X": -582.5132,
|
"DataId": 33918,
|
||||||
"Y": 40.54578,
|
"Locations": [
|
||||||
"Z": -426.0171
|
{
|
||||||
}
|
"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,
|
"Nodes": [
|
||||||
"Position": {
|
{
|
||||||
"X": -578.2101,
|
"DataId": 33920,
|
||||||
"Y": 41.27147,
|
"Locations": [
|
||||||
"Z": -447.6376
|
{
|
||||||
}
|
"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,
|
"Nodes": [
|
||||||
"Position": {
|
{
|
||||||
"X": -488.2276,
|
"DataId": 33922,
|
||||||
"Y": 34.71221,
|
"Locations": [
|
||||||
"Z": -359.6945
|
{
|
||||||
}
|
"Position": {
|
||||||
},
|
"X": -304.0609,
|
||||||
{
|
"Y": 68.76999,
|
||||||
"DataId": 33921,
|
"Z": -479.1875
|
||||||
"Position": {
|
},
|
||||||
"X": -498.8687,
|
"MinimumAngle": -110,
|
||||||
"Y": 31.08014,
|
"MaximumAngle": 70
|
||||||
"Z": -351.9397
|
}
|
||||||
}
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DataId": 33922,
|
"DataId": 33923,
|
||||||
"Position": {
|
"Locations": [
|
||||||
"X": -304.0609,
|
{
|
||||||
"Y": 68.76999,
|
"Position": {
|
||||||
"Z": -479.1875
|
"X": -293.6989,
|
||||||
}
|
"Y": 68.77935,
|
||||||
},
|
"Z": -484.2256
|
||||||
{
|
},
|
||||||
"DataId": 33923,
|
"MinimumAngle": -30,
|
||||||
"Position": {
|
"MaximumAngle": 110
|
||||||
"X": -293.6989,
|
},
|
||||||
"Y": 68.77935,
|
{
|
||||||
"Z": -484.2256
|
"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)
|
if (_locations == null)
|
||||||
{
|
{
|
||||||
_locations = [];
|
_locations = [];
|
||||||
#if RELEASE
|
|
||||||
LoadLocations();
|
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 =>
|
public static Stream QuestSchema =>
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
<AdditionalFiles Include="..\Questionable.Model\common-schema.json" />
|
<AdditionalFiles Include="..\Questionable.Model\common-schema.json" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup Condition="'$(Configuration)' == 'Release'">
|
<ItemGroup>
|
||||||
<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" />
|
||||||
|
@ -25,41 +25,64 @@
|
|||||||
"AetheryteShortcut": {
|
"AetheryteShortcut": {
|
||||||
"$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/Aetheryte"
|
"$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/Aetheryte"
|
||||||
},
|
},
|
||||||
"Nodes": {
|
"Groups": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"DataId": {
|
"Nodes": {
|
||||||
"type": "number",
|
"type": "array",
|
||||||
"minimum": 30000,
|
"items": {
|
||||||
"maximum": 50000
|
"type": "object",
|
||||||
},
|
"properties": {
|
||||||
"Position": {
|
"DataId": {
|
||||||
"$ref": "#/$defs/Vector3"
|
"type": "number",
|
||||||
},
|
"minimum": 30000,
|
||||||
"MinimumAngle": {
|
"maximum": 50000
|
||||||
"type": "number",
|
},
|
||||||
"minimum": -360,
|
"Locations": {
|
||||||
"maximum": 360
|
"type": "array",
|
||||||
},
|
"items": {
|
||||||
"MaximumAngle": {
|
"type": "object",
|
||||||
"type": "number",
|
"properties": {
|
||||||
"minimum": -360,
|
"Position": {
|
||||||
"maximum": 360
|
"$ref": "#/$defs/Vector3"
|
||||||
},
|
},
|
||||||
"MinimumDistance": {
|
"MinimumAngle": {
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"minimum": 0
|
"minimum": -360,
|
||||||
},
|
"maximum": 360
|
||||||
"MaximumDistance": {
|
},
|
||||||
"type": "number",
|
"MaximumAngle": {
|
||||||
"exclusiveMinimum": 0
|
"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": [
|
"required": [
|
||||||
"DataId",
|
"Nodes"
|
||||||
"Position"
|
|
||||||
],
|
],
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
}
|
}
|
||||||
|
@ -153,7 +153,7 @@ public class GatheringSourceGenerator : ISourceGenerator
|
|||||||
Assignment(nameof(GatheringRoot.TerritoryId), root.TerritoryId, default)
|
Assignment(nameof(GatheringRoot.TerritoryId), root.TerritoryId, default)
|
||||||
.AsSyntaxNodeOrToken(),
|
.AsSyntaxNodeOrToken(),
|
||||||
Assignment(nameof(GatheringRoot.AetheryteShortcut), root.AetheryteShortcut, null),
|
Assignment(nameof(GatheringRoot.AetheryteShortcut), root.AetheryteShortcut, null),
|
||||||
AssignmentList(nameof(GatheringRoot.Nodes), root.Nodes).AsSyntaxNodeOrToken()))));
|
AssignmentList(nameof(GatheringRoot.Groups), root.Groups).AsSyntaxNodeOrToken()))));
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@ -314,30 +314,55 @@ public static class RoslynShortcuts
|
|||||||
Assignment(nameof(SkipAetheryteCondition.InSameTerritory),
|
Assignment(nameof(SkipAetheryteCondition.InSameTerritory),
|
||||||
skipAetheryteCondition.InSameTerritory, emptyAetheryte.InSameTerritory)))));
|
skipAetheryteCondition.InSameTerritory, emptyAetheryte.InSameTerritory)))));
|
||||||
}
|
}
|
||||||
else if (value is GatheringNodeLocation nodeLocation)
|
else if (value is GatheringNodeGroup nodeGroup)
|
||||||
{
|
{
|
||||||
var emptyLocation = new GatheringNodeLocation();
|
|
||||||
return ObjectCreationExpression(
|
return ObjectCreationExpression(
|
||||||
IdentifierName(nameof(GatheringNodeLocation)))
|
IdentifierName(nameof(GatheringNodeGroup)))
|
||||||
.WithInitializer(
|
.WithInitializer(
|
||||||
InitializerExpression(
|
InitializerExpression(
|
||||||
SyntaxKind.ObjectInitializerExpression,
|
SyntaxKind.ObjectInitializerExpression,
|
||||||
SeparatedList<ExpressionSyntax>(
|
SeparatedList<ExpressionSyntax>(
|
||||||
SyntaxNodeList(
|
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)
|
emptyLocation.DataId)
|
||||||
.AsSyntaxNodeOrToken(),
|
.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(),
|
emptyLocation.Position).AsSyntaxNodeOrToken(),
|
||||||
Assignment(nameof(GatheringNodeLocation.MinimumAngle), nodeLocation.MinimumAngle,
|
Assignment(nameof(GatheringLocation.MinimumAngle), location.MinimumAngle,
|
||||||
emptyLocation.MinimumAngle).AsSyntaxNodeOrToken(),
|
emptyLocation.MinimumAngle).AsSyntaxNodeOrToken(),
|
||||||
Assignment(nameof(GatheringNodeLocation.MaximumAngle), nodeLocation.MaximumAngle,
|
Assignment(nameof(GatheringLocation.MaximumAngle), location.MaximumAngle,
|
||||||
emptyLocation.MaximumAngle).AsSyntaxNodeOrToken(),
|
emptyLocation.MaximumAngle).AsSyntaxNodeOrToken(),
|
||||||
Assignment(nameof(GatheringNodeLocation.MinimumDistance),
|
Assignment(nameof(GatheringLocation.MinimumDistance),
|
||||||
nodeLocation.MinimumDistance, emptyLocation.MinimumDistance)
|
location.MinimumDistance, emptyLocation.MinimumDistance)
|
||||||
.AsSyntaxNodeOrToken(),
|
.AsSyntaxNodeOrToken(),
|
||||||
Assignment(nameof(GatheringNodeLocation.MaximumDistance),
|
Assignment(nameof(GatheringLocation.MaximumDistance),
|
||||||
nodeLocation.MaximumDistance, emptyLocation.MaximumDistance)
|
location.MaximumDistance, emptyLocation.MaximumDistance)
|
||||||
.AsSyntaxNodeOrToken()))));
|
.AsSyntaxNodeOrToken()))));
|
||||||
}
|
}
|
||||||
else if (value is null)
|
else if (value is null)
|
||||||
|
@ -55,12 +55,13 @@ public static class Utils
|
|||||||
Culture = CultureInfo.InvariantCulture,
|
Culture = CultureInfo.InvariantCulture,
|
||||||
OutputFormat = OutputFormat.List,
|
OutputFormat = OutputFormat.List,
|
||||||
});
|
});
|
||||||
if (!evaluationResult.IsValid)
|
if (evaluationResult.HasErrors)
|
||||||
{
|
{
|
||||||
var error = Diagnostic.Create(invalidJson,
|
var error = Diagnostic.Create(invalidJson,
|
||||||
null,
|
null,
|
||||||
Path.GetFileName(additionalFile.Path));
|
Path.GetFileName(additionalFile.Path));
|
||||||
context.ReportDiagnostic(error);
|
context.ReportDiagnostic(error);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
yield return (id, node);
|
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))]
|
[JsonConverter(typeof(AetheryteConverter))]
|
||||||
public EAetheryteLocation? AetheryteShortcut { get; set; }
|
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
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GatheringPathRenderer", "GatheringPathRenderer\GatheringPathRenderer.csproj", "{F514DA95-9867-4F3F-8062-ACE0C62E8740}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GatheringPathRenderer", "GatheringPathRenderer\GatheringPathRenderer.csproj", "{F514DA95-9867-4F3F-8062-ACE0C62E8740}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ECommons", "vendor\ECommons\ECommons\ECommons.csproj", "{A12D7B4B-8E6E-4DCF-A41A-12F62E9FF94B}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|x64 = Debug|x64
|
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}.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.ActiveCfg = Release|Any CPU
|
||||||
{F514DA95-9867-4F3F-8062-ACE0C62E8740}.Release|x64.Build.0 = 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
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
@ -8,6 +8,7 @@ using System.Linq;
|
|||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using System.Text.Json.Nodes;
|
using System.Text.Json.Nodes;
|
||||||
using Dalamud.Plugin;
|
using Dalamud.Plugin;
|
||||||
|
using Dalamud.Plugin.Ipc;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Questionable.Data;
|
using Questionable.Data;
|
||||||
using Questionable.Model;
|
using Questionable.Model;
|
||||||
@ -23,8 +24,9 @@ internal sealed class QuestRegistry
|
|||||||
private readonly IDalamudPluginInterface _pluginInterface;
|
private readonly IDalamudPluginInterface _pluginInterface;
|
||||||
private readonly QuestData _questData;
|
private readonly QuestData _questData;
|
||||||
private readonly QuestValidator _questValidator;
|
private readonly QuestValidator _questValidator;
|
||||||
private readonly ILogger<QuestRegistry> _logger;
|
|
||||||
private readonly JsonSchemaValidator _jsonSchemaValidator;
|
private readonly JsonSchemaValidator _jsonSchemaValidator;
|
||||||
|
private readonly ILogger<QuestRegistry> _logger;
|
||||||
|
private readonly ICallGateProvider<object> _reloadDataIpc;
|
||||||
|
|
||||||
private readonly Dictionary<ushort, Quest> _quests = new();
|
private readonly Dictionary<ushort, Quest> _quests = new();
|
||||||
|
|
||||||
@ -37,6 +39,7 @@ internal sealed class QuestRegistry
|
|||||||
_questValidator = questValidator;
|
_questValidator = questValidator;
|
||||||
_jsonSchemaValidator = jsonSchemaValidator;
|
_jsonSchemaValidator = jsonSchemaValidator;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
_reloadDataIpc = _pluginInterface.GetIpcProvider<object>("Questionable.ReloadData");
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<Quest> AllQuests => _quests.Values;
|
public IEnumerable<Quest> AllQuests => _quests.Values;
|
||||||
@ -66,6 +69,7 @@ internal sealed class QuestRegistry
|
|||||||
|
|
||||||
ValidateQuests();
|
ValidateQuests();
|
||||||
Reloaded?.Invoke(this, EventArgs.Empty);
|
Reloaded?.Invoke(this, EventArgs.Empty);
|
||||||
|
_reloadDataIpc.SendMessage();
|
||||||
_logger.LogInformation("Loaded {Count} quests in total", _quests.Count);
|
_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