227 lines
7.6 KiB
C#
227 lines
7.6 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Numerics;
|
|
using System.Text.Json;
|
|
using System.Text.Json.Nodes;
|
|
using System.Text.Json.Serialization;
|
|
using System.Text.Json.Serialization.Metadata;
|
|
using Dalamud.Game.ClientState.Objects;
|
|
using Dalamud.Game.ClientState.Objects.Enums;
|
|
using Dalamud.Game.ClientState.Objects.Types;
|
|
using Dalamud.Game.Command;
|
|
using Dalamud.Plugin.Services;
|
|
using Lumina.Excel.GeneratedSheets;
|
|
using Questionable.Model;
|
|
using Questionable.Model.Gathering;
|
|
using Questionable.Model.Questing;
|
|
|
|
namespace GatheringPathRenderer;
|
|
|
|
internal sealed class EditorCommands : IDisposable
|
|
{
|
|
private readonly RendererPlugin _plugin;
|
|
private readonly IDataManager _dataManager;
|
|
private readonly ICommandManager _commandManager;
|
|
private readonly ITargetManager _targetManager;
|
|
private readonly IClientState _clientState;
|
|
private readonly IChatGui _chatGui;
|
|
private readonly Configuration _configuration;
|
|
|
|
public EditorCommands(RendererPlugin plugin, IDataManager dataManager, ICommandManager commandManager,
|
|
ITargetManager targetManager, IClientState clientState, IChatGui chatGui, Configuration configuration)
|
|
{
|
|
_plugin = plugin;
|
|
_dataManager = dataManager;
|
|
_commandManager = commandManager;
|
|
_targetManager = targetManager;
|
|
_clientState = clientState;
|
|
_chatGui = chatGui;
|
|
_configuration = configuration;
|
|
|
|
_commandManager.AddHandler("/qg", new CommandInfo(ProcessCommand));
|
|
}
|
|
|
|
private void ProcessCommand(string command, string argument)
|
|
{
|
|
string[] parts = argument.Split(' ');
|
|
string subCommand = parts[0];
|
|
List<string> arguments = parts.Skip(1).ToList();
|
|
|
|
try
|
|
{
|
|
switch (subCommand)
|
|
{
|
|
case "add":
|
|
CreateOrAddLocationToGroup(arguments);
|
|
break;
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
_chatGui.PrintError(e.ToString(), "qG");
|
|
}
|
|
}
|
|
|
|
private void CreateOrAddLocationToGroup(List<string> arguments)
|
|
{
|
|
var target = _targetManager.Target;
|
|
if (target == null || target.ObjectKind != ObjectKind.GatheringPoint)
|
|
throw new Exception("No valid target");
|
|
|
|
var gatheringPoint = _dataManager.GetExcelSheet<GatheringPoint>()!.GetRow(target.DataId);
|
|
if (gatheringPoint == null)
|
|
throw new Exception("Invalid gathering point");
|
|
|
|
FileInfo targetFile;
|
|
GatheringRoot root;
|
|
var locationsInTerritory = _plugin.GetLocationsInTerritory(_clientState.TerritoryType).ToList();
|
|
var location = locationsInTerritory.SingleOrDefault(x => x.Id == gatheringPoint.GatheringPointBase.Row);
|
|
if (location != null)
|
|
{
|
|
targetFile = location.File;
|
|
root = location.Root;
|
|
|
|
// if this is an existing node, ignore it
|
|
var existingNode = root.Groups.SelectMany(x => x.Nodes.Where(y => y.DataId == target.DataId))
|
|
.Any(x => x.Locations.Any(y => Vector3.Distance(y.Position, target.Position) < 0.1f));
|
|
if (existingNode)
|
|
throw new Exception("Node already exists");
|
|
|
|
if (arguments.Contains("group"))
|
|
AddToNewGroup(root, target);
|
|
else
|
|
AddToExistingGroup(root, target);
|
|
}
|
|
else
|
|
{
|
|
(targetFile, root) = CreateNewFile(gatheringPoint, target);
|
|
_chatGui.Print($"Creating new file under {targetFile.FullName}", "qG");
|
|
}
|
|
|
|
_plugin.Save(targetFile, root);
|
|
}
|
|
|
|
public void AddToNewGroup(GatheringRoot root, IGameObject target)
|
|
{
|
|
root.Groups.Add(new GatheringNodeGroup
|
|
{
|
|
Nodes =
|
|
[
|
|
new GatheringNode
|
|
{
|
|
DataId = target.DataId,
|
|
Locations =
|
|
[
|
|
new GatheringLocation
|
|
{
|
|
Position = target.Position,
|
|
}
|
|
]
|
|
}
|
|
]
|
|
});
|
|
_chatGui.Print("Added group.", "qG");
|
|
}
|
|
|
|
public void AddToExistingGroup(GatheringRoot root, IGameObject target)
|
|
{
|
|
// find the same data id
|
|
var node = root.Groups.SelectMany(x => x.Nodes)
|
|
.SingleOrDefault(x => x.DataId == target.DataId);
|
|
if (node != null)
|
|
{
|
|
node.Locations.Add(new GatheringLocation
|
|
{
|
|
Position = target.Position,
|
|
});
|
|
_chatGui.Print($"Added location to existing node {target.DataId}.", "qG");
|
|
}
|
|
else
|
|
{
|
|
// find the closest group
|
|
var closestGroup = root.Groups
|
|
.Select(group => new
|
|
{
|
|
Group = group,
|
|
Distance = group.Nodes.Min(x =>
|
|
x.Locations.Min(y =>
|
|
Vector3.Distance(_clientState.LocalPlayer!.Position, y.Position)))
|
|
})
|
|
.OrderBy(x => x.Distance)
|
|
.First();
|
|
|
|
closestGroup.Group.Nodes.Add(new GatheringNode
|
|
{
|
|
DataId = target.DataId,
|
|
Locations =
|
|
[
|
|
new GatheringLocation
|
|
{
|
|
Position = target.Position,
|
|
}
|
|
]
|
|
});
|
|
_chatGui.Print($"Added new node {target.DataId}.", "qG");
|
|
}
|
|
}
|
|
|
|
public (FileInfo targetFile, GatheringRoot root) CreateNewFile(GatheringPoint gatheringPoint, IGameObject target)
|
|
{
|
|
// determine target folder
|
|
DirectoryInfo? targetFolder = _plugin.GetLocationsInTerritory(_clientState.TerritoryType).FirstOrDefault()
|
|
?.File.Directory;
|
|
if (targetFolder == null)
|
|
{
|
|
var territoryInfo = _dataManager.GetExcelSheet<TerritoryType>()!.GetRow(_clientState.TerritoryType)!;
|
|
targetFolder = _plugin.PathsDirectory
|
|
.CreateSubdirectory(ExpansionData.ExpansionFolders[(EExpansionVersion)territoryInfo.ExVersion.Row])
|
|
.CreateSubdirectory(territoryInfo.PlaceName.Value!.Name.ToString());
|
|
}
|
|
|
|
FileInfo targetFile =
|
|
new FileInfo(
|
|
Path.Combine(targetFolder.FullName,
|
|
$"{gatheringPoint.GatheringPointBase.Row}_{gatheringPoint.PlaceName.Value!.Name}_{(_clientState.LocalPlayer!.ClassJob.Id == 16 ? "MIN" : "BTN")}.json"));
|
|
var root = new GatheringRoot
|
|
{
|
|
Author = [_configuration.AuthorName],
|
|
Steps =
|
|
[
|
|
new QuestStep
|
|
{
|
|
TerritoryId = _clientState.TerritoryType,
|
|
InteractionType = EInteractionType.None,
|
|
}
|
|
],
|
|
Groups =
|
|
[
|
|
new GatheringNodeGroup
|
|
{
|
|
Nodes =
|
|
[
|
|
new GatheringNode
|
|
{
|
|
DataId = target.DataId,
|
|
Locations =
|
|
[
|
|
new GatheringLocation
|
|
{
|
|
Position = target.Position
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
};
|
|
return (targetFile, root);
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
_commandManager.RemoveHandler("/qg");
|
|
}
|
|
}
|