forked from liza/Workshoppa
NET 8
This commit is contained in:
parent
7d5cbd8563
commit
b61de1f52c
1017
.editorconfig
Normal file
1017
.editorconfig
Normal file
File diff suppressed because it is too large
Load Diff
2
LLib
2
LLib
@ -1 +1 @@
|
||||
Subproject commit 865a6080319f8ccbcd5fd5b0004404822b6e60d4
|
||||
Subproject commit 3792244261a9f5426a7916f5a6dd1966238ba84a
|
6
Workshoppa.sln.DotSettings
Normal file
6
Workshoppa.sln.DotSettings
Normal file
@ -0,0 +1,6 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Amalj_0027aa/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Ceruleum/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Workshoppa/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Yesno/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Z_0027ranmaia/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
@ -10,7 +10,7 @@ internal sealed class Configuration : IPluginConfiguration
|
||||
{
|
||||
public int Version { get; set; } = 1;
|
||||
|
||||
public CurrentItem? CurrentlyCraftedItem { get; set; } = null;
|
||||
public CurrentItem? CurrentlyCraftedItem { get; set; }
|
||||
public List<QueuedItem> ItemQueue { get; set; } = new();
|
||||
public bool EnableRepairKitCalculator { get; set; } = true;
|
||||
public bool EnableCeruleumTankCalculator { get; set; } = true;
|
||||
@ -27,7 +27,7 @@ internal sealed class Configuration : IPluginConfiguration
|
||||
public uint WorkshopItemId { get; set; }
|
||||
public bool StartedCrafting { get; set; }
|
||||
|
||||
public uint PhasesComplete { get; set; } = 0;
|
||||
public uint PhasesComplete { get; set; }
|
||||
public List<PhaseItem> ContributedItemsInCurrentPhase { get; set; } = new();
|
||||
|
||||
public bool UpdateFromCraftState(CraftState craftState)
|
||||
|
@ -8,7 +8,7 @@ public sealed class CraftState
|
||||
public required uint ResultItem { get; init; }
|
||||
public required uint StepsComplete { get; init; }
|
||||
public required uint StepsTotal { get; init; }
|
||||
public required List<CraftItem> Items { get; init; }
|
||||
public required IReadOnlyList<CraftItem> Items { get; init; }
|
||||
|
||||
public bool IsPhaseComplete() => Items.All(x => x.Finished || x.StepsComplete == x.StepsTotal);
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Text.RegularExpressions;
|
||||
using Dalamud.Plugin.Services;
|
||||
using LLib;
|
||||
@ -13,19 +14,19 @@ internal sealed class GameStrings
|
||||
public GameStrings(IDataManager dataManager, IPluginLog pluginLog)
|
||||
{
|
||||
PurchaseItemForGil = dataManager.GetRegex<Addon>(3406, addon => addon.Text, pluginLog)
|
||||
?? throw new Exception($"Unable to resolve {nameof(PurchaseItemForGil)}");
|
||||
?? throw new ConstraintException($"Unable to resolve {nameof(PurchaseItemForGil)}");
|
||||
PurchaseItemForCompanyCredits = dataManager.GetRegex<Addon>(3473, addon => addon.Text, pluginLog)
|
||||
?? throw new Exception($"Unable to resolve {nameof(PurchaseItemForCompanyCredits)}");
|
||||
?? throw new ConstraintException($"Unable to resolve {nameof(PurchaseItemForCompanyCredits)}");
|
||||
ViewCraftingLog =
|
||||
dataManager.GetString<WorkshopDialogue>("TEXT_CMNDEFCOMPANYMANUFACTORY_00150_MENU_CC_NOTE",
|
||||
pluginLog) ?? throw new Exception($"Unable to resolve {nameof(ViewCraftingLog)}");
|
||||
pluginLog) ?? throw new ConstraintException($"Unable to resolve {nameof(ViewCraftingLog)}");
|
||||
TurnInHighQualityItem = dataManager.GetString<Addon>(102434, addon => addon.Text, pluginLog)
|
||||
?? throw new Exception($"Unable to resolve {nameof(TurnInHighQualityItem)}");
|
||||
?? throw new ConstraintException($"Unable to resolve {nameof(TurnInHighQualityItem)}");
|
||||
ContributeItems = dataManager.GetRegex<Addon>(6652, addon => addon.Text, pluginLog)
|
||||
?? throw new Exception($"Unable to resolve {nameof(ContributeItems)}");
|
||||
?? throw new ConstraintException($"Unable to resolve {nameof(ContributeItems)}");
|
||||
RetrieveFinishedItem =
|
||||
dataManager.GetRegex<WorkshopDialogue>("TEXT_CMNDEFCOMPANYMANUFACTORY_00150_FINISH_CONF", pluginLog)
|
||||
?? throw new Exception($"Unable to resolve {nameof(RetrieveFinishedItem)}");
|
||||
?? throw new ConstraintException($"Unable to resolve {nameof(RetrieveFinishedItem)}");
|
||||
}
|
||||
|
||||
public Regex PurchaseItemForGil { get; }
|
||||
@ -36,7 +37,8 @@ internal sealed class GameStrings
|
||||
public Regex RetrieveFinishedItem { get; }
|
||||
|
||||
[Sheet("custom/001/CmnDefCompanyManufactory_00150")]
|
||||
private class WorkshopDialogue : QuestDialogueText
|
||||
[SuppressMessage("Performance", "CA1812")]
|
||||
private sealed class WorkshopDialogue : QuestDialogueText
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ using Lumina.Excel.GeneratedSheets;
|
||||
|
||||
namespace Workshoppa.GameData;
|
||||
|
||||
public sealed class RecipeTree
|
||||
internal sealed class RecipeTree
|
||||
{
|
||||
private readonly IDataManager _dataManager;
|
||||
private readonly IReadOnlyList<uint> _shopItemsOnly;
|
||||
@ -38,7 +38,7 @@ public sealed class RecipeTree
|
||||
.AsReadOnly();
|
||||
}
|
||||
|
||||
public List<Ingredient> ResolveRecipes(List<Ingredient> materials)
|
||||
public IReadOnlyList<Ingredient> ResolveRecipes(IReadOnlyList<Ingredient> materials)
|
||||
{
|
||||
// look up recipes recursively
|
||||
int limit = 10;
|
||||
@ -72,7 +72,8 @@ public sealed class RecipeTree
|
||||
//_pluginLog.Information($" → {part.Name}");
|
||||
|
||||
int unmodifiedQuantity = part.TotalQuantity;
|
||||
int roundedQuantity = (int)((unmodifiedQuantity + ingredient.AmountCrafted - 1) / ingredient.AmountCrafted);
|
||||
int roundedQuantity =
|
||||
(int)((unmodifiedQuantity + ingredient.AmountCrafted - 1) / ingredient.AmountCrafted);
|
||||
part.TotalQuantity = part.TotalQuantity - unmodifiedQuantity + roundedQuantity;
|
||||
}
|
||||
}
|
||||
@ -83,13 +84,13 @@ public sealed class RecipeTree
|
||||
List<RecipeInfo> sortedList = new List<RecipeInfo>();
|
||||
while (sortedList.Count < completeList.Count)
|
||||
{
|
||||
var craftable = completeList.Where(x =>
|
||||
!sortedList.Contains(x) && x.DependsOn.All(y => sortedList.Any(z => y == z.ItemId)))
|
||||
var canBeCrafted = completeList.Where(x =>
|
||||
!sortedList.Contains(x) && x.DependsOn.All(y => sortedList.Any(z => y == z.ItemId)))
|
||||
.ToList();
|
||||
if (craftable.Count == 0)
|
||||
throw new Exception("Unable to sort items");
|
||||
if (canBeCrafted.Count == 0)
|
||||
throw new InvalidOperationException("Unable to sort items");
|
||||
|
||||
sortedList.AddRange(craftable.OrderBy(x => x.Name));
|
||||
sortedList.AddRange(canBeCrafted.OrderBy(x => x.Name));
|
||||
}
|
||||
|
||||
return sortedList.Cast<Ingredient>().ToList();
|
||||
@ -142,7 +143,7 @@ public sealed class RecipeTree
|
||||
return ingredients;
|
||||
}
|
||||
|
||||
private List<RecipeInfo> ExtendWithAmountCrafted(List<Ingredient> materials)
|
||||
private List<RecipeInfo> ExtendWithAmountCrafted(IEnumerable<Ingredient> materials)
|
||||
{
|
||||
return materials.Select(x => new
|
||||
{
|
||||
@ -164,17 +165,17 @@ public sealed class RecipeTree
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public Recipe? GetFirstRecipeForItem(uint itemId)
|
||||
private Recipe? GetFirstRecipeForItem(uint itemId)
|
||||
{
|
||||
return _dataManager.GetExcelSheet<Recipe>()!.FirstOrDefault(x => x.RowId > 0 && x.ItemResult.Row == itemId);
|
||||
}
|
||||
|
||||
public GatheringItem? GetGatheringItem(uint itemId)
|
||||
private GatheringItem? GetGatheringItem(uint itemId)
|
||||
{
|
||||
return _dataManager.GetExcelSheet<GatheringItem>()!.FirstOrDefault(x => x.RowId > 0 && (uint)x.Item == itemId);
|
||||
}
|
||||
|
||||
public RetainerTaskNormal? GetVentureItem(uint itemId)
|
||||
private RetainerTaskNormal? GetVentureItem(uint itemId)
|
||||
{
|
||||
return _dataManager.GetExcelSheet<RetainerTaskNormal>()!
|
||||
.FirstOrDefault(x => x.RowId > 0 && x.Item.Row == itemId);
|
||||
|
@ -129,7 +129,7 @@ internal sealed class CeruleumTankWindow : ShopWindow
|
||||
}
|
||||
}
|
||||
|
||||
private string FormatStackCount(int ceruleumTanks)
|
||||
private static string FormatStackCount(int ceruleumTanks)
|
||||
{
|
||||
int fullStacks = ceruleumTanks / 999;
|
||||
int partials = ceruleumTanks % 999;
|
||||
|
@ -1,12 +1,11 @@
|
||||
using System.Numerics;
|
||||
using Dalamud.Interface.Windowing;
|
||||
using Dalamud.Plugin;
|
||||
using ImGuiNET;
|
||||
using LLib;
|
||||
using LLib.ImGui;
|
||||
|
||||
namespace Workshoppa.Windows;
|
||||
|
||||
internal sealed class ConfigWindow : LImGui.LWindow
|
||||
internal sealed class ConfigWindow : LWindow
|
||||
{
|
||||
private readonly DalamudPluginInterface _pluginInterface;
|
||||
private readonly Configuration _configuration;
|
||||
|
@ -13,12 +13,13 @@ using Dalamud.Plugin.Services;
|
||||
using FFXIVClientStructs.FFXIV.Client.Game;
|
||||
using ImGuiNET;
|
||||
using LLib;
|
||||
using LLib.ImGui;
|
||||
using Workshoppa.GameData;
|
||||
|
||||
namespace Workshoppa.Windows;
|
||||
|
||||
// FIXME The close button doesn't work near the workshop, either hide it or make it work
|
||||
internal sealed class MainWindow : LImGui.LWindow
|
||||
internal sealed class MainWindow : LWindow
|
||||
{
|
||||
private static readonly Regex CountAndName = new(@"^(\d{1,5})x?\s+(.*)$", RegexOptions.Compiled);
|
||||
|
||||
@ -231,7 +232,7 @@ internal sealed class MainWindow : LImGui.LWindow
|
||||
ImGui.InputTextWithHint("", "Filter...", ref _searchString, 256);
|
||||
|
||||
foreach (var craft in _workshopCache.Crafts
|
||||
.Where(x => x.Name.ToLower().Contains(_searchString.ToLower()))
|
||||
.Where(x => x.Name.Contains(_searchString, StringComparison.OrdinalIgnoreCase))
|
||||
.OrderBy(x => x.WorkshopItemId))
|
||||
{
|
||||
IDalamudTextureWrap? icon = _iconCache.GetIcon(craft.IconId);
|
||||
@ -319,7 +320,7 @@ internal sealed class MainWindow : LImGui.LWindow
|
||||
ImGui.InputTextWithHint("", "Preset Name...", ref _newPresetName, 64);
|
||||
|
||||
ImGui.BeginDisabled(_configuration.Presets.Any(x =>
|
||||
x.Name.Equals(_newPresetName, StringComparison.CurrentCultureIgnoreCase)));
|
||||
x.Name.Equals(_newPresetName, StringComparison.OrdinalIgnoreCase)));
|
||||
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Save, "Save"))
|
||||
{
|
||||
_configuration.Presets.Add(new Configuration.Preset
|
||||
@ -400,7 +401,7 @@ internal sealed class MainWindow : LImGui.LWindow
|
||||
continue;
|
||||
|
||||
var craft = _workshopCache.Crafts.FirstOrDefault(x =>
|
||||
x.Name.Equals(match.Groups[2].Value, StringComparison.CurrentCultureIgnoreCase));
|
||||
x.Name.Equals(match.Groups[2].Value, StringComparison.OrdinalIgnoreCase));
|
||||
if (craft != null && int.TryParse(match.Groups[1].Value, out int quantity))
|
||||
{
|
||||
fromClipboardItems.Add(new Configuration.QueuedItem
|
||||
@ -590,7 +591,7 @@ internal sealed class MainWindow : LImGui.LWindow
|
||||
.ToList();
|
||||
}
|
||||
|
||||
private void AddMaterial(Dictionary<uint, int> completedForCurrentCraft, uint itemId, int quantity)
|
||||
private static void AddMaterial(Dictionary<uint, int> completedForCurrentCraft, uint itemId, int quantity)
|
||||
{
|
||||
if (completedForCurrentCraft.TryGetValue(itemId, out var existingQuantity))
|
||||
completedForCurrentCraft[itemId] = quantity + existingQuantity;
|
||||
|
@ -6,14 +6,14 @@ using Dalamud.Plugin.Services;
|
||||
using FFXIVClientStructs.FFXIV.Client.Game;
|
||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||
using ImGuiNET;
|
||||
using LLib;
|
||||
using LLib.GameUI;
|
||||
using LLib.ImGui;
|
||||
using Workshoppa.External;
|
||||
using Workshoppa.GameData.Shops;
|
||||
|
||||
namespace Workshoppa.Windows;
|
||||
|
||||
internal abstract class ShopWindow : LImGui.LWindow, IDisposable
|
||||
internal abstract class ShopWindow : LWindow, IDisposable
|
||||
{
|
||||
private readonly string _addonName;
|
||||
private readonly WorkshopPlugin _plugin;
|
||||
|
@ -51,12 +51,12 @@ partial class WorkshopPlugin
|
||||
|
||||
private void SelectCraftBranch()
|
||||
{
|
||||
if (SelectSelectString("contrib", 0, s => s.StartsWith("Contribute materials.")))
|
||||
if (SelectSelectString("contrib", 0, s => s.StartsWith("Contribute materials.", StringComparison.Ordinal)))
|
||||
{
|
||||
CurrentStage = Stage.ContributeMaterials;
|
||||
_continueAt = DateTime.Now.AddSeconds(1);
|
||||
}
|
||||
else if (SelectSelectString("advance", 0, s => s.StartsWith("Advance to the next phase of production.")))
|
||||
else if (SelectSelectString("advance", 0, s => s.StartsWith("Advance to the next phase of production.", StringComparison.Ordinal)))
|
||||
{
|
||||
_pluginLog.Information("Phase is complete");
|
||||
|
||||
@ -67,7 +67,7 @@ partial class WorkshopPlugin
|
||||
CurrentStage = Stage.TargetFabricationStation;
|
||||
_continueAt = DateTime.Now.AddSeconds(3);
|
||||
}
|
||||
else if (SelectSelectString("complete", 0, s => s.StartsWith("Complete the construction of")))
|
||||
else if (SelectSelectString("complete", 0, s => s.StartsWith("Complete the construction of", StringComparison.Ordinal)))
|
||||
{
|
||||
_pluginLog.Information("Item is almost complete, confirming last cutscene");
|
||||
CurrentStage = Stage.TargetFabricationStation;
|
||||
|
@ -119,7 +119,7 @@ partial class WorkshopPlugin
|
||||
|
||||
private void ConfirmCraft()
|
||||
{
|
||||
if (SelectSelectYesno(0, s => s.StartsWith("Craft ")))
|
||||
if (SelectSelectYesno(0, s => s.StartsWith("Craft ", StringComparison.Ordinal)))
|
||||
{
|
||||
_configuration.CurrentlyCraftedItem!.StartedCrafting = true;
|
||||
_pluginInterface.SavePluginConfig(_configuration);
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Dalamud.Game.ClientState.Objects.Enums;
|
||||
@ -122,7 +123,9 @@ partial class WorkshopPlugin
|
||||
LAddon.IsAddonReady(&addonSelectYesno->AtkUnitBase))
|
||||
{
|
||||
var text = MemoryHelper.ReadSeString(&addonSelectYesno->PromptText->NodeText).ToString();
|
||||
text = text.Replace("\n", "").Replace("\r", "");
|
||||
text = text
|
||||
.Replace("\n", "", StringComparison.Ordinal)
|
||||
.Replace("\r", "", StringComparison.Ordinal);
|
||||
if (predicate(text))
|
||||
{
|
||||
_pluginLog.Information($"Selecting choice {choice} for '{text}'");
|
||||
@ -184,17 +187,22 @@ partial class WorkshopPlugin
|
||||
return null;
|
||||
}
|
||||
|
||||
private uint ParseAtkItemCountHq(AtkValue atkValue)
|
||||
private static uint ParseAtkItemCountHq(AtkValue atkValue)
|
||||
{
|
||||
// NQ / HQ string
|
||||
// I have no clue, but it doesn't seme like the available HQ item count is strored anywhere in the atkvalues??
|
||||
string? s = atkValue.ReadAtkString();
|
||||
if (s != null)
|
||||
{
|
||||
var parts = s.Replace("\ue03c", "").Split('/');
|
||||
var parts = s.Replace("\ue03c", "", StringComparison.Ordinal).Split('/');
|
||||
if (parts.Length > 1)
|
||||
{
|
||||
return uint.Parse(parts[1].Replace(",", "").Replace(".", "").Trim());
|
||||
return uint.Parse(
|
||||
parts[1]
|
||||
.Replace(",", "", StringComparison.Ordinal)
|
||||
.Replace(".", "", StringComparison.Ordinal)
|
||||
.Trim(),
|
||||
CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,9 @@ partial class WorkshopPlugin
|
||||
_pluginLog.Verbose("SelectYesNo post-setup");
|
||||
|
||||
AddonSelectYesno* addonSelectYesNo = (AddonSelectYesno*)args.Addon;
|
||||
string text = MemoryHelper.ReadSeString(&addonSelectYesNo->PromptText->NodeText).ToString().Replace("\n", "").Replace("\r", "");
|
||||
string text = MemoryHelper.ReadSeString(&addonSelectYesNo->PromptText->NodeText).ToString()
|
||||
.Replace("\n", "", StringComparison.Ordinal)
|
||||
.Replace("\r", "", StringComparison.Ordinal);
|
||||
_pluginLog.Verbose($"YesNo prompt: '{text}'");
|
||||
|
||||
if (_repairKitWindow.IsOpen)
|
||||
|
@ -15,7 +15,7 @@ using Workshoppa.Windows;
|
||||
|
||||
namespace Workshoppa;
|
||||
|
||||
[SuppressMessage("ReSharper", "UnusedType.Global")]
|
||||
[SuppressMessage("ReSharper", "ClassNeverInstantiated.Global")]
|
||||
public sealed partial class WorkshopPlugin : IDalamudPlugin
|
||||
{
|
||||
private readonly IReadOnlyList<uint> _fabricationStationIds =
|
||||
|
@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0-windows</TargetFramework>
|
||||
<Version>4.3</Version>
|
||||
<TargetFramework>net8.0-windows</TargetFramework>
|
||||
<Version>5.0</Version>
|
||||
<LangVersion>11.0</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"version": 1,
|
||||
"dependencies": {
|
||||
"net7.0-windows7.0": {
|
||||
"net8.0-windows7.0": {
|
||||
"DalamudPackager": {
|
||||
"type": "Direct",
|
||||
"requested": "[2.1.12, )",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"sdk": {
|
||||
"version": "7.0.0",
|
||||
"version": "8.0.0",
|
||||
"rollForward": "latestMinor",
|
||||
"allowPrerelease": false
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user