Fix 'Export Material List to Clipboard'
This commit is contained in:
parent
ccfb6b7423
commit
3a0bb492fa
@ -2,18 +2,20 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using Lumina.Excel.GeneratedSheets;
|
using Lumina.Excel.GeneratedSheets2;
|
||||||
|
|
||||||
namespace Workshoppa.GameData;
|
namespace Workshoppa.GameData;
|
||||||
|
|
||||||
internal sealed class RecipeTree
|
internal sealed class RecipeTree
|
||||||
{
|
{
|
||||||
private readonly IDataManager _dataManager;
|
private readonly IDataManager _dataManager;
|
||||||
|
private readonly IPluginLog _pluginLog;
|
||||||
private readonly IReadOnlyList<uint> _shopItemsOnly;
|
private readonly IReadOnlyList<uint> _shopItemsOnly;
|
||||||
|
|
||||||
public RecipeTree(IDataManager dataManager)
|
public RecipeTree(IDataManager dataManager, IPluginLog pluginLog)
|
||||||
{
|
{
|
||||||
_dataManager = dataManager;
|
_dataManager = dataManager;
|
||||||
|
_pluginLog = pluginLog;
|
||||||
|
|
||||||
// probably incomplete, e.g. different housing districts have different shop types
|
// probably incomplete, e.g. different housing districts have different shop types
|
||||||
var shopVendorIds = new uint[]
|
var shopVendorIds = new uint[]
|
||||||
@ -62,6 +64,9 @@ internal sealed class RecipeTree
|
|||||||
AmountCrafted = x.First().AmountCrafted,
|
AmountCrafted = x.First().AmountCrafted,
|
||||||
})
|
})
|
||||||
.ToList();
|
.ToList();
|
||||||
|
_pluginLog.Verbose("Complete craft list:");
|
||||||
|
foreach (var item in completeList)
|
||||||
|
_pluginLog.Verbose($" {item.TotalQuantity}x {item.Name}");
|
||||||
|
|
||||||
// if a recipe has a specific amount crafted, divide the gathered amount by it
|
// if a recipe has a specific amount crafted, divide the gathered amount by it
|
||||||
foreach (var ingredient in completeList.Where(x => x is { AmountCrafted: > 1 }))
|
foreach (var ingredient in completeList.Where(x => x is { AmountCrafted: > 1 }))
|
||||||
@ -84,11 +89,18 @@ internal sealed class RecipeTree
|
|||||||
List<RecipeInfo> sortedList = new List<RecipeInfo>();
|
List<RecipeInfo> sortedList = new List<RecipeInfo>();
|
||||||
while (sortedList.Count < completeList.Count)
|
while (sortedList.Count < completeList.Count)
|
||||||
{
|
{
|
||||||
|
_pluginLog.Verbose("Sort round");
|
||||||
var canBeCrafted = completeList.Where(x =>
|
var canBeCrafted = completeList.Where(x =>
|
||||||
!sortedList.Contains(x) && x.DependsOn.All(y => sortedList.Any(z => y == z.ItemId)))
|
!sortedList.Contains(x) && x.DependsOn.All(y => sortedList.Any(z => y == z.ItemId)))
|
||||||
.ToList();
|
.ToList();
|
||||||
|
foreach (var item in canBeCrafted)
|
||||||
|
_pluginLog.Verbose($" can craft: {item.TotalQuantity}x {item.Name}");
|
||||||
if (canBeCrafted.Count == 0)
|
if (canBeCrafted.Count == 0)
|
||||||
|
{
|
||||||
|
foreach (var item in completeList.Where(x => !sortedList.Contains(x)))
|
||||||
|
_pluginLog.Warning($" can't craft: {item.TotalQuantity}x {item.Name} → ({string.Join(", ", item.DependsOn.Where(y => sortedList.All(z => y != z.ItemId)))})");
|
||||||
throw new InvalidOperationException("Unable to sort items");
|
throw new InvalidOperationException("Unable to sort items");
|
||||||
|
}
|
||||||
|
|
||||||
sortedList.AddRange(canBeCrafted.OrderBy(x => x.Name));
|
sortedList.AddRange(canBeCrafted.OrderBy(x => x.Name));
|
||||||
}
|
}
|
||||||
@ -107,33 +119,34 @@ internal sealed class RecipeTree
|
|||||||
if (recipe == null)
|
if (recipe == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
foreach (var ingredient in recipe.UnkData5.Take(8))
|
for (int i = 0; i < 8; ++ i)
|
||||||
{
|
{
|
||||||
if (ingredient == null || ingredient.ItemIngredient == 0)
|
var ingredient = recipe.Ingredient[i];
|
||||||
|
if (ingredient == null || ingredient.Row == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Item? item = _dataManager.GetExcelSheet<Item>()!.GetRow((uint)ingredient.ItemIngredient);
|
Item? item = ingredient.Value;
|
||||||
if (item == null)
|
if (item == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Recipe? ingredientRecipe = GetFirstRecipeForItem((uint)ingredient.ItemIngredient);
|
Recipe? ingredientRecipe = GetFirstRecipeForItem(ingredient.Row);
|
||||||
|
|
||||||
//_pluginLog.Information($"Adding {item.Name}");
|
//_pluginLog.Information($"Adding {item.Name}");
|
||||||
ingredients.Add(new RecipeInfo
|
ingredients.Add(new RecipeInfo
|
||||||
{
|
{
|
||||||
ItemId = (uint)ingredient.ItemIngredient,
|
ItemId = ingredient.Row,
|
||||||
Name = item.Name,
|
Name = item.Name,
|
||||||
TotalQuantity = material.TotalQuantity * ingredient.AmountIngredient,
|
TotalQuantity = material.TotalQuantity * recipe.AmountIngredient[i],
|
||||||
Type =
|
Type =
|
||||||
_shopItemsOnly.Contains((uint)ingredient.ItemIngredient) ? Ingredient.EType.ShopItem :
|
_shopItemsOnly.Contains(ingredient.Row) ? Ingredient.EType.ShopItem :
|
||||||
ingredientRecipe != null ? Ingredient.EType.Craftable :
|
ingredientRecipe != null ? Ingredient.EType.Craftable :
|
||||||
GetGatheringItem((uint)ingredient.ItemIngredient) != null ? Ingredient.EType.Gatherable :
|
GetGatheringItem(ingredient.Row) != null ? Ingredient.EType.Gatherable :
|
||||||
GetVentureItem((uint)ingredient.ItemIngredient) != null ? Ingredient.EType.Gatherable :
|
GetVentureItem(ingredient.Row) != null ? Ingredient.EType.Gatherable :
|
||||||
Ingredient.EType.Other,
|
Ingredient.EType.Other,
|
||||||
|
|
||||||
AmountCrafted = ingredientRecipe?.AmountResult ?? 1,
|
AmountCrafted = ingredientRecipe?.AmountResult ?? 1,
|
||||||
DependsOn = ingredientRecipe?.UnkData5.Take(8).Where(x => x != null && x.ItemIngredient != 0)
|
DependsOn = ingredientRecipe?.Ingredient.Where(x => x != null && IsValidItem(x.Row))
|
||||||
.Select(x => (uint)x.ItemIngredient)
|
.Select(x => x.Row)
|
||||||
.ToList()
|
.ToList()
|
||||||
?? new(),
|
?? new(),
|
||||||
});
|
});
|
||||||
@ -158,8 +171,8 @@ internal sealed class RecipeTree
|
|||||||
TotalQuantity = x.Ingredient.TotalQuantity,
|
TotalQuantity = x.Ingredient.TotalQuantity,
|
||||||
Type = _shopItemsOnly.Contains(x.Ingredient.ItemId) ? Ingredient.EType.ShopItem : x.Ingredient.Type,
|
Type = _shopItemsOnly.Contains(x.Ingredient.ItemId) ? Ingredient.EType.ShopItem : x.Ingredient.Type,
|
||||||
AmountCrafted = x.Recipe!.AmountResult,
|
AmountCrafted = x.Recipe!.AmountResult,
|
||||||
DependsOn = x.Recipe.UnkData5.Take(8).Where(y => y != null && y.ItemIngredient != 0)
|
DependsOn = x.Recipe.Ingredient.Where(y => y != null && IsValidItem(y.Row))
|
||||||
.Select(y => (uint)y.ItemIngredient)
|
.Select(y => y.Row)
|
||||||
.ToList(),
|
.ToList(),
|
||||||
})
|
})
|
||||||
.ToList();
|
.ToList();
|
||||||
@ -172,7 +185,7 @@ internal sealed class RecipeTree
|
|||||||
|
|
||||||
private GatheringItem? GetGatheringItem(uint itemId)
|
private GatheringItem? GetGatheringItem(uint itemId)
|
||||||
{
|
{
|
||||||
return _dataManager.GetExcelSheet<GatheringItem>()!.FirstOrDefault(x => x.RowId > 0 && (uint)x.Item == itemId);
|
return _dataManager.GetExcelSheet<GatheringItem>()!.FirstOrDefault(x => x.RowId > 0 && x.Item.Row == itemId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private RetainerTaskNormal? GetVentureItem(uint itemId)
|
private RetainerTaskNormal? GetVentureItem(uint itemId)
|
||||||
@ -181,6 +194,11 @@ internal sealed class RecipeTree
|
|||||||
.FirstOrDefault(x => x.RowId > 0 && x.Item.Row == itemId);
|
.FirstOrDefault(x => x.RowId > 0 && x.Item.Row == itemId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsValidItem(uint itemId)
|
||||||
|
{
|
||||||
|
return itemId != 0 && itemId != uint.MaxValue;
|
||||||
|
}
|
||||||
|
|
||||||
private sealed class RecipeInfo : Ingredient
|
private sealed class RecipeInfo : Ingredient
|
||||||
{
|
{
|
||||||
public required uint AmountCrafted { get; init; }
|
public required uint AmountCrafted { get; init; }
|
||||||
|
@ -72,7 +72,7 @@ public sealed partial class WorkshopPlugin : IDalamudPlugin
|
|||||||
_gameStrings = new(dataManager, _pluginLog);
|
_gameStrings = new(dataManager, _pluginLog);
|
||||||
|
|
||||||
_mainWindow = new(this, _pluginInterface, _clientState, _configuration, _workshopCache,
|
_mainWindow = new(this, _pluginInterface, _clientState, _configuration, _workshopCache,
|
||||||
new IconCache(textureProvider), _chatGui, new RecipeTree(dataManager), _pluginLog);
|
new IconCache(textureProvider), _chatGui, new RecipeTree(dataManager, _pluginLog), _pluginLog);
|
||||||
_windowSystem.AddWindow(_mainWindow);
|
_windowSystem.AddWindow(_mainWindow);
|
||||||
_configWindow = new(_pluginInterface, _configuration);
|
_configWindow = new(_pluginInterface, _configuration);
|
||||||
_windowSystem.AddWindow(_configWindow);
|
_windowSystem.AddWindow(_configWindow);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<Project Sdk="Dalamud.NET.Sdk/9.0.2">
|
<Project Sdk="Dalamud.NET.Sdk/9.0.2">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Version>6.0</Version>
|
<Version>6.1</Version>
|
||||||
<OutputPath>dist</OutputPath>
|
<OutputPath>dist</OutputPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user