From 7b415b4e478b56d38b3a7685969980b74e1dcbe6 Mon Sep 17 00:00:00 2001 From: CakeAndBanana Date: Mon, 29 Sep 2025 18:37:02 +0200 Subject: [PATCH 01/10] Changed it to so debug shows while in debug mode. --- LightlessSync/UI/BroadcastUI.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LightlessSync/UI/BroadcastUI.cs b/LightlessSync/UI/BroadcastUI.cs index 4977fb6..2076f6c 100644 --- a/LightlessSync/UI/BroadcastUI.cs +++ b/LightlessSync/UI/BroadcastUI.cs @@ -309,7 +309,7 @@ namespace LightlessSync.UI ImGui.EndTabItem(); } - +#if DEBUG if (ImGui.BeginTabItem("Debug")) { ImGui.Text("Broadcast Cache"); @@ -365,7 +365,7 @@ namespace LightlessSync.UI ImGui.EndTable(); } - +#endif ImGui.EndTabItem(); } From f74cd01a3290ff5de3821d6af4345276ad527fc5 Mon Sep 17 00:00:00 2001 From: CakeAndBanana Date: Mon, 29 Sep 2025 19:44:36 +0200 Subject: [PATCH 02/10] Pair request button only shows when lightfinder is on --- LightlessSync/Plugin.cs | 2 +- LightlessSync/UI/ContextMenu.cs | 23 +++++++++++++++-------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/LightlessSync/Plugin.cs b/LightlessSync/Plugin.cs index 3529735..24f1745 100644 --- a/LightlessSync/Plugin.cs +++ b/LightlessSync/Plugin.cs @@ -147,7 +147,7 @@ public sealed class Plugin : IDalamudPlugin collection.AddSingleton(); collection.AddSingleton(); collection.AddSingleton(addonLifecycle); - collection.AddSingleton(p => new ContextMenu(contextMenu, pluginInterface, gameData, p.GetRequiredService>(), p.GetRequiredService(), p.GetRequiredService(), objectTable)); + collection.AddSingleton(p => new ContextMenu(contextMenu, pluginInterface, gameData, p.GetRequiredService>(), p.GetRequiredService(), p.GetRequiredService(), objectTable, p.GetRequiredService())); collection.AddSingleton((s) => new IpcCallerPenumbra(s.GetRequiredService>(), pluginInterface, s.GetRequiredService(), s.GetRequiredService(), s.GetRequiredService())); collection.AddSingleton((s) => new IpcCallerGlamourer(s.GetRequiredService>(), pluginInterface, diff --git a/LightlessSync/UI/ContextMenu.cs b/LightlessSync/UI/ContextMenu.cs index 1e1cfc3..4a4ed62 100644 --- a/LightlessSync/UI/ContextMenu.cs +++ b/LightlessSync/UI/ContextMenu.cs @@ -3,6 +3,7 @@ using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Game.Gui.ContextMenu; using Dalamud.Plugin; using Dalamud.Plugin.Services; +using LightlessSync.LightlessConfiguration; using LightlessSync.Services; using LightlessSync.Utils; using LightlessSync.WebAPI; @@ -19,6 +20,7 @@ internal class ContextMenu : IHostedService private readonly IDataManager _gameData; private readonly ILogger _logger; private readonly DalamudUtilService _dalamudUtil; + private readonly LightlessConfigService _configService; private readonly ApiController _apiController; private readonly IObjectTable _objectTable; @@ -37,7 +39,8 @@ internal class ContextMenu : IHostedService ILogger logger, DalamudUtilService dalamudUtil, ApiController apiController, - IObjectTable objectTable) + IObjectTable objectTable, + LightlessConfigService configService) { _contextMenu = contextMenu; _pluginInterface = pluginInterface; @@ -46,6 +49,7 @@ internal class ContextMenu : IHostedService _dalamudUtil = dalamudUtil; _apiController = apiController; _objectTable = objectTable; + _configService = configService; } public Task StartAsync(CancellationToken cancellationToken) @@ -90,14 +94,17 @@ internal class ContextMenu : IHostedService if (!IsWorldValid(world)) return; - args.AddMenuItem(new MenuItem + if (_configService.Current.BroadcastEnabled) { - Name = "Send Pair Request", - PrefixChar = 'L', - UseDefaultPrefix = false, - PrefixColor = 708, - OnClicked = async _ => await HandleSelection(args) - }); + args.AddMenuItem(new MenuItem + { + Name = "Send Pair Request", + PrefixChar = 'L', + UseDefaultPrefix = false, + PrefixColor = 708, + OnClicked = async _ => await HandleSelection(args) + }); + } } private async Task HandleSelection(IMenuArgs args) From dc1fdd4a3e0816818f98fd894a18a633d80b618e Mon Sep 17 00:00:00 2001 From: CakeAndBanana Date: Mon, 29 Sep 2025 19:52:19 +0200 Subject: [PATCH 03/10] Removed the lightfinder needs to be turned on. --- LightlessSync/UI/ContextMenu.cs | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/LightlessSync/UI/ContextMenu.cs b/LightlessSync/UI/ContextMenu.cs index 4a4ed62..e34a694 100644 --- a/LightlessSync/UI/ContextMenu.cs +++ b/LightlessSync/UI/ContextMenu.cs @@ -94,17 +94,14 @@ internal class ContextMenu : IHostedService if (!IsWorldValid(world)) return; - if (_configService.Current.BroadcastEnabled) + args.AddMenuItem(new MenuItem { - args.AddMenuItem(new MenuItem - { - Name = "Send Pair Request", - PrefixChar = 'L', - UseDefaultPrefix = false, - PrefixColor = 708, - OnClicked = async _ => await HandleSelection(args) - }); - } + Name = "Send Pair Request", + PrefixChar = 'L', + UseDefaultPrefix = false, + PrefixColor = 708, + OnClicked = async _ => await HandleSelection(args) + }); } private async Task HandleSelection(IMenuArgs args) From 7d6d500e6a7436837980918dc3d553557ac8e54d Mon Sep 17 00:00:00 2001 From: CakeAndBanana Date: Mon, 29 Sep 2025 22:38:38 +0200 Subject: [PATCH 04/10] Changes from Bites to Bytes. --- LightlessSync/UI/ContextMenu.cs | 5 ++--- LightlessSync/UI/UISharedService.cs | 10 ++++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/LightlessSync/UI/ContextMenu.cs b/LightlessSync/UI/ContextMenu.cs index e34a694..5a8b291 100644 --- a/LightlessSync/UI/ContextMenu.cs +++ b/LightlessSync/UI/ContextMenu.cs @@ -1,5 +1,4 @@ using Dalamud.Game.ClientState.Objects.SubKinds; -using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Game.Gui.ContextMenu; using Dalamud.Plugin; using Dalamud.Plugin.Services; @@ -81,7 +80,7 @@ internal class ContextMenu : IHostedService if (!_pluginInterface.UiBuilder.ShouldModifyUi) return; - if (!ValidAddons.Contains(args.AddonName)) + if (!ValidAddons.Contains(args.AddonName, StringComparer.Ordinal)) return; if (args.Target is not MenuTargetDefault target) @@ -127,7 +126,7 @@ internal class ContextMenu : IHostedService return; } - var senderCid = (await _dalamudUtil.GetCIDAsync()).ToString().GetHash256(); + var senderCid = (await _dalamudUtil.GetCIDAsync().ConfigureAwait(false)).ToString().GetHash256(); var receiverCid = DalamudUtilService.GetHashedCIDFromPlayerPointer(targetData.Address); _logger.LogInformation("Sending pair request: sender {SenderCid}, receiver {ReceiverCid}", senderCid, receiverCid); diff --git a/LightlessSync/UI/UISharedService.cs b/LightlessSync/UI/UISharedService.cs index e4753dc..7fdf97f 100644 --- a/LightlessSync/UI/UISharedService.cs +++ b/LightlessSync/UI/UISharedService.cs @@ -173,12 +173,14 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase public static string ByteToString(long bytes, bool addSuffix = true) { - string[] suffix = ["B", "KiB", "MiB", "GiB", "TiB"]; - int i; + string[] suffix = { "B", "KB", "MB", "GB", "TB" }; + int i = 0; double dblSByte = bytes; - for (i = 0; i < suffix.Length && bytes >= 1024; i++, bytes /= 1024) + + while (dblSByte >= 1000 && i < suffix.Length - 1) { - dblSByte = bytes / 1024.0; + dblSByte /= 1000.0; + i++; } return addSuffix ? $"{dblSByte:0.00} {suffix[i]}" : $"{dblSByte:0.00}"; From 8a9d4b8daa81f6c7a432662273ace589e0550978 Mon Sep 17 00:00:00 2001 From: CakeAndBanana Date: Mon, 29 Sep 2025 23:19:02 +0200 Subject: [PATCH 05/10] Added more byte options --- LightlessSync/UI/UISharedService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LightlessSync/UI/UISharedService.cs b/LightlessSync/UI/UISharedService.cs index 7fdf97f..9a935ba 100644 --- a/LightlessSync/UI/UISharedService.cs +++ b/LightlessSync/UI/UISharedService.cs @@ -173,7 +173,7 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase public static string ByteToString(long bytes, bool addSuffix = true) { - string[] suffix = { "B", "KB", "MB", "GB", "TB" }; + string[] suffix = { "B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"}; int i = 0; double dblSByte = bytes; From 0b7b543dd7e07439a7935b7c2c90a28e59930693 Mon Sep 17 00:00:00 2001 From: CakeAndBanana Date: Mon, 29 Sep 2025 23:56:11 +0200 Subject: [PATCH 06/10] Add Group check, reworked world check for instances. --- LightlessSync/UI/BroadcastUI.cs | 21 ++++++++------------- LightlessSync/UI/ContextMenu.cs | 24 +++++++++++++++++++++++- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/LightlessSync/UI/BroadcastUI.cs b/LightlessSync/UI/BroadcastUI.cs index 2076f6c..6d50184 100644 --- a/LightlessSync/UI/BroadcastUI.cs +++ b/LightlessSync/UI/BroadcastUI.cs @@ -22,7 +22,7 @@ namespace LightlessSync.UI private IReadOnlyList _allSyncshells; private string _userUid = string.Empty; - private List<(string Label, string? GID, bool IsAvailable)> _syncshellOptions = new(); + private readonly List<(string Label, string? GID, bool IsAvailable)> _syncshellOptions = new(); public BroadcastUI( ILogger logger, @@ -48,7 +48,7 @@ namespace LightlessSync.UI MaximumSize = new(750, 400) }; - mediator.Subscribe(this, async _ => await RefreshSyncshells()); + mediator.Subscribe(this, async _ => await RefreshSyncshells().ConfigureAwait(false)); } private void RebuildSyncshellDropdownOptions() @@ -62,7 +62,7 @@ namespace LightlessSync.UI _syncshellOptions.Clear(); _syncshellOptions.Add(("None", null, true)); - var addedGids = new HashSet(); + var addedGids = new HashSet(StringComparer.Ordinal); foreach (var shell in ownedSyncshells) { @@ -73,7 +73,7 @@ namespace LightlessSync.UI if (!string.IsNullOrEmpty(selectedGid) && !addedGids.Contains(selectedGid)) { - var matching = allSyncshells.FirstOrDefault(g => g.GID == selectedGid); + var matching = allSyncshells.FirstOrDefault(g => string.Equals(g.GID, selectedGid, StringComparison.Ordinal)); if (matching != null) { var label = matching.GroupAliasOrGID ?? matching.GID; @@ -97,7 +97,7 @@ namespace LightlessSync.UI { if (!_apiController.IsConnected) { - _allSyncshells = Array.Empty(); + _allSyncshells = []; RebuildSyncshellDropdownOptions(); return; } @@ -109,7 +109,7 @@ namespace LightlessSync.UI catch (Exception ex) { _logger.LogError(ex, "Failed to fetch Syncshells."); - _allSyncshells = Array.Empty(); + _allSyncshells = []; } RebuildSyncshellDropdownOptions(); @@ -260,14 +260,14 @@ namespace LightlessSync.UI } var selectedGid = _configService.Current.SelectedFinderSyncshell; - var currentOption = _syncshellOptions.FirstOrDefault(o => o.GID == selectedGid); + var currentOption = _syncshellOptions.FirstOrDefault(o => string.Equals(o.GID, selectedGid, StringComparison.Ordinal)); var preview = currentOption.Label ?? "Select a Syncshell..."; if (ImGui.BeginCombo("##SyncshellDropdown", preview)) { foreach (var (label, gid, available) in _syncshellOptions) { - bool isSelected = gid == selectedGid; + bool isSelected = string.Equals(gid, selectedGid, StringComparison.Ordinal); if (!available) ImGui.PushStyleColor(ImGuiCol.Text, UIColors.Get("DimRed")); @@ -373,10 +373,5 @@ namespace LightlessSync.UI ImGui.EndTabBar(); } } - - protected override void Dispose(bool disposing) - { - base.Dispose(disposing); - } } } diff --git a/LightlessSync/UI/ContextMenu.cs b/LightlessSync/UI/ContextMenu.cs index 5a8b291..80bbb0c 100644 --- a/LightlessSync/UI/ContextMenu.cs +++ b/LightlessSync/UI/ContextMenu.cs @@ -9,6 +9,7 @@ using LightlessSync.WebAPI; using Lumina.Excel.Sheets; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; +using System.Linq; namespace LightlessSync.UI; @@ -141,8 +142,29 @@ internal class ContextMenu : IHostedService private World GetWorld(uint worldId) { var sheet = _gameData.GetExcelSheet()!; - return sheet.TryGetRow(worldId, out var world) ? world : sheet.First(); + var luminaWorlds = sheet.Where(x => + { + var dc = x.DataCenter.ValueNullable; + var name = x.Name.ExtractText(); + var internalName = x.InternalName.ExtractText(); + + if (dc == null || dc.Value.Region == 0 || string.IsNullOrWhiteSpace(dc.Value.Name.ExtractText())) + return false; + + if (string.IsNullOrWhiteSpace(name) || string.IsNullOrWhiteSpace(internalName)) + return false; + + if (name.Contains('-', StringComparison.Ordinal) || name.Contains('_', StringComparison.Ordinal)) + return false; + + return x.RowId > 3001 && IsChineseJapaneseKoreanString(name); + }); + + return luminaWorlds.FirstOrDefault(x => x.RowId == worldId); } + private static bool IsChineseJapaneseKoreanString(string text) => text.All(IsChineseJapaneseKoreanCharacter); + + private static bool IsChineseJapaneseKoreanCharacter(char c) => (c >= 0x4E00 && c <= 0x9FFF); public bool IsWorldValid(uint worldId) => IsWorldValid(GetWorld(worldId)); From 9696ac60f1fe8ac65863263a48ab1cf90d3be25b Mon Sep 17 00:00:00 2001 From: CakeAndBanana Date: Tue, 30 Sep 2025 00:00:11 +0200 Subject: [PATCH 07/10] Added region bound. --- LightlessSync/UI/ContextMenu.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/LightlessSync/UI/ContextMenu.cs b/LightlessSync/UI/ContextMenu.cs index 80bbb0c..19b5955 100644 --- a/LightlessSync/UI/ContextMenu.cs +++ b/LightlessSync/UI/ContextMenu.cs @@ -157,9 +157,15 @@ internal class ContextMenu : IHostedService if (name.Contains('-', StringComparison.Ordinal) || name.Contains('_', StringComparison.Ordinal)) return false; - return x.RowId > 3001 && IsChineseJapaneseKoreanString(name); + return x.DataCenter.Value.Region != 5 || x.RowId > 3001 && x.RowId != 1200 && IsChineseJapaneseKoreanString(name); }); + foreach (var world in luminaWorlds) + { + _logger.LogInformation(message: $"ID: {world.RowId} - World: {world.Name.ExtractText()}"); + } + _logger.LogInformation(message: $"Character is in World: {worldId}"); + return luminaWorlds.FirstOrDefault(x => x.RowId == worldId); } private static bool IsChineseJapaneseKoreanString(string text) => text.All(IsChineseJapaneseKoreanCharacter); From e85b9007546dbbf4c715daa28b97cfcd71b0f875 Mon Sep 17 00:00:00 2001 From: azyges Date: Tue, 30 Sep 2025 11:17:55 +0900 Subject: [PATCH 08/10] some ui updates --- LightlessSync/UI/BroadcastUI.cs | 5 +- LightlessSync/UI/DataAnalysisUi.cs | 207 +++++++++++++++++----------- LightlessSync/UI/SettingsUi.cs | 17 +++ LightlessSync/UI/UISharedService.cs | 15 ++ 4 files changed, 158 insertions(+), 86 deletions(-) diff --git a/LightlessSync/UI/BroadcastUI.cs b/LightlessSync/UI/BroadcastUI.cs index 6d50184..eda5a53 100644 --- a/LightlessSync/UI/BroadcastUI.cs +++ b/LightlessSync/UI/BroadcastUI.cs @@ -309,7 +309,8 @@ namespace LightlessSync.UI ImGui.EndTabItem(); } -#if DEBUG + + #if DEBUG if (ImGui.BeginTabItem("Debug")) { ImGui.Text("Broadcast Cache"); @@ -365,10 +366,10 @@ namespace LightlessSync.UI ImGui.EndTable(); } -#endif ImGui.EndTabItem(); } + #endif ImGui.EndTabBar(); } diff --git a/LightlessSync/UI/DataAnalysisUi.cs b/LightlessSync/UI/DataAnalysisUi.cs index e1ef15c..5b750f3 100644 --- a/LightlessSync/UI/DataAnalysisUi.cs +++ b/LightlessSync/UI/DataAnalysisUi.cs @@ -547,73 +547,147 @@ public class DataAnalysisUi : WindowMediatorSubscriberBase using var tab = ImRaii.TabItem(tabText + "###" + kvp.Key.ToString()); if (tab.Success) { - var groupedfiles = kvp.Value.Select(v => v.Value).GroupBy(f => f.FileType, StringComparer.Ordinal) - .OrderBy(k => k.Key, StringComparer.Ordinal).ToList(); + var groupedfiles = kvp.Value.Select(v => v.Value).GroupBy(f => f.FileType, StringComparer.Ordinal).OrderBy(k => k.Key, StringComparer.Ordinal).ToList(); - ImGui.TextUnformatted("Files for " + kvp.Key); - ImGui.SameLine(); - ImGui.TextUnformatted(kvp.Value.Count.ToString()); - ImGui.SameLine(); + ImGui.PushStyleVar(ImGuiStyleVar.CellPadding, new Vector2(1f, 1f)); + ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, new Vector2(1f, 1f)); - using (var font = ImRaii.PushFont(UiBuilder.IconFont)) + if (ImGui.BeginTable($"##fileStats_{kvp.Key}", 3, + ImGuiTableFlags.BordersInnerV | ImGuiTableFlags.SizingFixedFit)) { - ImGui.TextUnformatted(FontAwesomeIcon.InfoCircle.ToIconString()); - } - if (ImGui.IsItemHovered()) - { - string text = ""; - text = string.Join(Environment.NewLine, groupedfiles - .Select(f => f.Key + ": " + f.Count() + " files, size: " + UiSharedService.ByteToString(f.Sum(v => v.OriginalSize)) - + ", compressed: " + UiSharedService.ByteToString(f.Sum(v => v.CompressedSize)))); - ImGui.SetTooltip(text); - } - ImGui.TextUnformatted($"{kvp.Key} size (actual):"); - ImGui.SameLine(); - ImGui.TextUnformatted(UiSharedService.ByteToString(kvp.Value.Sum(c => c.Value.OriginalSize))); - ImGui.TextUnformatted($"{kvp.Key} size (compressed for up/download only):"); - ImGui.SameLine(); - ImGui.TextUnformatted(UiSharedService.ByteToString(kvp.Value.Sum(c => c.Value.CompressedSize))); - ImGui.Separator(); - - var vramUsage = groupedfiles.SingleOrDefault(v => string.Equals(v.Key, "tex", StringComparison.Ordinal)); - if (vramUsage != null) - { - var actualVramUsage = vramUsage.Sum(f => f.OriginalSize); - ImGui.TextUnformatted($"{kvp.Key} VRAM usage:"); + ImGui.TableNextRow(); + ImGui.TableNextColumn(); + ImGui.TextUnformatted($"Files for {kvp.Key}"); + ImGui.TableNextColumn(); + ImGui.TextUnformatted(kvp.Value.Count.ToString()); ImGui.SameLine(); - ImGui.TextUnformatted(UiSharedService.ByteToString(actualVramUsage)); + using (var font = ImRaii.PushFont(UiBuilder.IconFont)) + ImGui.TextUnformatted(FontAwesomeIcon.InfoCircle.ToIconString()); + if (ImGui.IsItemHovered()) + { + string text = string.Join(Environment.NewLine, groupedfiles.Select(f => + $"{f.Key}: {f.Count()} files, size: {UiSharedService.ByteToString(f.Sum(v => v.OriginalSize))}, compressed: {UiSharedService.ByteToString(f.Sum(v => v.CompressedSize))}")); + ImGui.SetTooltip(text); + } + ImGui.TableNextColumn(); + + ImGui.TableNextRow(); + ImGui.TableNextColumn(); + ImGui.TextUnformatted($"{kvp.Key} size (actual):"); + ImGui.TableNextColumn(); + ImGui.TextUnformatted(UiSharedService.ByteToString(kvp.Value.Sum(c => c.Value.OriginalSize))); + ImGui.TableNextColumn(); + + ImGui.TableNextRow(); + ImGui.TableNextColumn(); + ImGui.TextUnformatted($"{kvp.Key} size (compressed for up/download only):"); + _uiSharedService.ColoredSeparator(UIColors.Get("LightlessPurpleDefault"), 1.5f); + ImGui.TableNextColumn(); + ImGui.TextUnformatted(UiSharedService.ByteToString(kvp.Value.Sum(c => c.Value.CompressedSize))); + _uiSharedService.ColoredSeparator(UIColors.Get("LightlessPurpleDefault"), 1.5f); + ImGui.TableNextColumn(); + + var vramUsage = groupedfiles.SingleOrDefault(v => string.Equals(v.Key, "tex", StringComparison.Ordinal)); + if (vramUsage != null) + { + var actualVramUsage = vramUsage.Sum(f => f.OriginalSize); + + ImGui.TableNextRow(); + ImGui.TableNextColumn(); + ImGui.TextUnformatted($"{kvp.Key} VRAM usage:"); + ImGui.TableNextColumn(); + ImGui.TextUnformatted(UiSharedService.ByteToString(actualVramUsage)); + ImGui.TableNextColumn(); + + if (_playerPerformanceConfig.Current.WarnOnExceedingThresholds + || _playerPerformanceConfig.Current.ShowPerformanceIndicator) + { + var currentVramWarning = _playerPerformanceConfig.Current.VRAMSizeWarningThresholdMiB; + + ImGui.TableNextRow(); + ImGui.TableNextColumn(); + ImGui.TextUnformatted("Configured VRAM threshold:"); + ImGui.TableNextColumn(); + ImGui.TextUnformatted($"{currentVramWarning} MiB."); + ImGui.TableNextColumn(); + if (currentVramWarning * 1024 * 1024 < actualVramUsage) + { + UiSharedService.ColorText( + $"You exceed your own threshold by {UiSharedService.ByteToString(actualVramUsage - (currentVramWarning * 1024 * 1024))}", + UIColors.Get("LightlessYellow")); + } + } + } + + var actualTriCount = kvp.Value.Sum(f => f.Value.Triangles); + ImGui.TableNextRow(); + ImGui.TableNextColumn(); + ImGui.TextUnformatted($"{kvp.Key} modded model triangles:"); + ImGui.TableNextColumn(); + ImGui.TextUnformatted(actualTriCount.ToString()); + ImGui.TableNextColumn(); + if (_playerPerformanceConfig.Current.WarnOnExceedingThresholds || _playerPerformanceConfig.Current.ShowPerformanceIndicator) { - using var _ = ImRaii.PushIndent(10f); - var currentVramWarning = _playerPerformanceConfig.Current.VRAMSizeWarningThresholdMiB; - ImGui.TextUnformatted($"Configured VRAM warning threshold: {currentVramWarning} MiB."); - if (currentVramWarning * 1024 * 1024 < actualVramUsage) + var currentTriWarning = _playerPerformanceConfig.Current.TrisWarningThresholdThousands; + + ImGui.TableNextRow(); + ImGui.TableNextColumn(); + ImGui.TextUnformatted("Configured triangle threshold:"); + ImGui.TableNextColumn(); + ImGui.TextUnformatted($"{currentTriWarning * 1000} triangles."); + ImGui.TableNextColumn(); + if (currentTriWarning * 1000 < actualTriCount) { - UiSharedService.ColorText($"You exceed your own threshold by " + - $"{UiSharedService.ByteToString(actualVramUsage - (currentVramWarning * 1024 * 1024))}.", + UiSharedService.ColorText( + $"You exceed your own threshold by {actualTriCount - (currentTriWarning * 1000)}", UIColors.Get("LightlessYellow")); } } + + ImGui.EndTable(); } - var actualTriCount = kvp.Value.Sum(f => f.Value.Triangles); - ImGui.TextUnformatted($"{kvp.Key} modded model triangles: {actualTriCount}"); - if (_playerPerformanceConfig.Current.WarnOnExceedingThresholds - || _playerPerformanceConfig.Current.ShowPerformanceIndicator) + ImGui.PopStyleVar(2); + + _uiSharedService.ColoredSeparator(UIColors.Get("LightlessPurple"), 2f); + + _uiSharedService.MediumText("Selected file:", UIColors.Get("LightlessBlue")); + ImGui.SameLine(); + _uiSharedService.MediumText(_selectedHash, UIColors.Get("LightlessYellow")); + + if (_cachedAnalysis[_selectedObjectTab].TryGetValue(_selectedHash, out CharacterAnalyzer.FileDataEntry? item)) { - using var _ = ImRaii.PushIndent(10f); - var currentTriWarning = _playerPerformanceConfig.Current.TrisWarningThresholdThousands; - ImGui.TextUnformatted($"Configured triangle warning threshold: {currentTriWarning * 1000} triangles."); - if (currentTriWarning * 1000 < actualTriCount) + var filePaths = item.FilePaths; + UiSharedService.ColorText("Local file path:", UIColors.Get("LightlessBlue")); + ImGui.SameLine(); + UiSharedService.TextWrapped(filePaths[0]); + if (filePaths.Count > 1) { - UiSharedService.ColorText($"You exceed your own threshold by " + - $"{actualTriCount - (currentTriWarning * 1000)} triangles.", - UIColors.Get("LightlessYellow")); + ImGui.SameLine(); + ImGui.TextUnformatted($"(and {filePaths.Count - 1} more)"); + ImGui.SameLine(); + _uiSharedService.IconText(FontAwesomeIcon.InfoCircle); + UiSharedService.AttachToolTip(string.Join(Environment.NewLine, filePaths.Skip(1))); + } + + var gamepaths = item.GamePaths; + UiSharedService.ColorText("Used by game path:", UIColors.Get("LightlessBlue")); + ImGui.SameLine(); + UiSharedService.TextWrapped(gamepaths[0]); + if (gamepaths.Count > 1) + { + ImGui.SameLine(); + ImGui.TextUnformatted($"(and {gamepaths.Count - 1} more)"); + ImGui.SameLine(); + _uiSharedService.IconText(FontAwesomeIcon.InfoCircle); + UiSharedService.AttachToolTip(string.Join(Environment.NewLine, gamepaths.Skip(1))); } } ImGui.Separator(); + if (_selectedObjectTab != kvp.Key) { _selectedHash = string.Empty; @@ -692,41 +766,6 @@ public class DataAnalysisUi : WindowMediatorSubscriberBase } } } - - ImGui.Separator(); - - ImGui.TextUnformatted("Selected file:"); - ImGui.SameLine(); - UiSharedService.ColorText(_selectedHash, UIColors.Get("LightlessYellow")); - - if (_cachedAnalysis[_selectedObjectTab].TryGetValue(_selectedHash, out CharacterAnalyzer.FileDataEntry? item)) - { - var filePaths = item.FilePaths; - ImGui.TextUnformatted("Local file path:"); - ImGui.SameLine(); - UiSharedService.TextWrapped(filePaths[0]); - if (filePaths.Count > 1) - { - ImGui.SameLine(); - ImGui.TextUnformatted($"(and {filePaths.Count - 1} more)"); - ImGui.SameLine(); - _uiSharedService.IconText(FontAwesomeIcon.InfoCircle); - UiSharedService.AttachToolTip(string.Join(Environment.NewLine, filePaths.Skip(1))); - } - - var gamepaths = item.GamePaths; - ImGui.TextUnformatted("Used by game path:"); - ImGui.SameLine(); - UiSharedService.TextWrapped(gamepaths[0]); - if (gamepaths.Count > 1) - { - ImGui.SameLine(); - ImGui.TextUnformatted($"(and {gamepaths.Count - 1} more)"); - ImGui.SameLine(); - _uiSharedService.IconText(FontAwesomeIcon.InfoCircle); - UiSharedService.AttachToolTip(string.Join(Environment.NewLine, gamepaths.Skip(1))); - } - } } public override void OnOpen() @@ -855,7 +894,7 @@ public class DataAnalysisUi : WindowMediatorSubscriberBase } var filePath = item.FilePaths[0]; bool toConvert = _texturesToConvert.ContainsKey(filePath); - if (ImGui.Checkbox("###convert" + item.Hash, ref toConvert)) + if (UiSharedService.CheckboxWithBorder("###convert" + item.Hash, ref toConvert, UIColors.Get("LightlessPurple"), 1.5f)) { if (toConvert && !_texturesToConvert.ContainsKey(filePath)) { diff --git a/LightlessSync/UI/SettingsUi.cs b/LightlessSync/UI/SettingsUi.cs index fdbe821..95bb2af 100644 --- a/LightlessSync/UI/SettingsUi.cs +++ b/LightlessSync/UI/SettingsUi.cs @@ -979,9 +979,17 @@ public class SettingsUi : WindowMediatorSubscriberBase var colorNames = new[] { ("LightlessPurple", "Lightless Purple", "Primary colors"), + ("LightlessPurpleActive", "Lightless Purple Active", "Primary colors"), + ("LightlessPurpleDefault", "Lightless Purple Inactive", "Primary colors"), ("LightlessBlue", "Lightless Blue", "Secondary colors"), + + ("LightlessGreen", "Lightless Green", "Active elements"), + ("LightlessYellow", "Lightless Yellow", "Warning colors"), + ("LightlessYellow2", "Lightless Yellow 2", "Warning colors"), + ("PairBlue", "Pair Blue", "Pair UI elements"), + ("DimRed", "Dim Red", "Error and offline") }; @@ -1020,6 +1028,8 @@ public class SettingsUi : WindowMediatorSubscriberBase ImGui.Spacing(); + _uiShared.ColoredSeparator(UIColors.Get("LightlessPurpleDefault"), 1.5f); + ImGui.TextUnformatted("Server Info Bar Colors"); if (ImGui.Checkbox("Color-code the Server Info Bar entry according to status", ref useColorsInDtr)) @@ -1054,6 +1064,9 @@ public class SettingsUi : WindowMediatorSubscriberBase } ImGui.Spacing(); + + _uiShared.ColoredSeparator(UIColors.Get("LightlessPurpleDefault"), 1.5f); + ImGui.TextUnformatted("Nameplate Colors"); var nameColorsEnabled = _configService.Current.IsNameplateColorsEnabled; @@ -1092,6 +1105,10 @@ public class SettingsUi : WindowMediatorSubscriberBase } } + ImGui.Spacing(); + + _uiShared.ColoredSeparator(UIColors.Get("LightlessPurpleDefault"), 1.5f); + if (ImGui.Checkbox("Use the complete redesign of the UI for Lightless client.", ref useLightlessRedesign)) { _configService.Current.UseLightlessRedesign = useLightlessRedesign; diff --git a/LightlessSync/UI/UISharedService.cs b/LightlessSync/UI/UISharedService.cs index 9a935ba..24899ee 100644 --- a/LightlessSync/UI/UISharedService.cs +++ b/LightlessSync/UI/UISharedService.cs @@ -512,6 +512,21 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase ImGui.Dummy(new Vector2(0, thickness * scale)); } + public static bool CheckboxWithBorder(string label, ref bool value, Vector4? borderColor = null, float borderThickness = 1.0f, float rounding = 3.0f) + { + var pos = ImGui.GetCursorScreenPos(); + + bool changed = ImGui.Checkbox(label, ref value); + + var min = pos; + var max = ImGui.GetItemRectMax(); + + var col = ImGui.GetColorU32(borderColor ?? ImGuiColors.DalamudGrey); + ImGui.GetWindowDrawList().AddRect(min, max, col, rounding, ImDrawFlags.None, borderThickness); + + return changed; + } + public void MediumText(string text, Vector4? color = null) { FontText(text, MediumFont, color); From 1fae47b1718a72ebe386dd2b3cd2a2be15930c1d Mon Sep 17 00:00:00 2001 From: CakeAndBanana Date: Tue, 30 Sep 2025 05:44:49 +0200 Subject: [PATCH 09/10] Removal of Logging of worlds for testing on what region I should needed --- LightlessSync/UI/ContextMenu.cs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/LightlessSync/UI/ContextMenu.cs b/LightlessSync/UI/ContextMenu.cs index 19b5955..6cdc90c 100644 --- a/LightlessSync/UI/ContextMenu.cs +++ b/LightlessSync/UI/ContextMenu.cs @@ -131,7 +131,7 @@ internal class ContextMenu : IHostedService var receiverCid = DalamudUtilService.GetHashedCIDFromPlayerPointer(targetData.Address); _logger.LogInformation("Sending pair request: sender {SenderCid}, receiver {ReceiverCid}", senderCid, receiverCid); - await _apiController.TryPairWithContentId(receiverCid, senderCid); + await _apiController.TryPairWithContentId(receiverCid, senderCid).ConfigureAwait(false); } catch (Exception ex) { @@ -160,12 +160,6 @@ internal class ContextMenu : IHostedService return x.DataCenter.Value.Region != 5 || x.RowId > 3001 && x.RowId != 1200 && IsChineseJapaneseKoreanString(name); }); - foreach (var world in luminaWorlds) - { - _logger.LogInformation(message: $"ID: {world.RowId} - World: {world.Name.ExtractText()}"); - } - _logger.LogInformation(message: $"Character is in World: {worldId}"); - return luminaWorlds.FirstOrDefault(x => x.RowId == worldId); } private static bool IsChineseJapaneseKoreanString(string text) => text.All(IsChineseJapaneseKoreanCharacter); From 597a0beb91aeceb8e14511e27980e8d74f8a06a1 Mon Sep 17 00:00:00 2001 From: CakeAndBanana Date: Tue, 30 Sep 2025 05:50:39 +0200 Subject: [PATCH 10/10] Added check if context user is in range or in object table. --- LightlessSync/UI/ContextMenu.cs | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/LightlessSync/UI/ContextMenu.cs b/LightlessSync/UI/ContextMenu.cs index 6cdc90c..b828cdd 100644 --- a/LightlessSync/UI/ContextMenu.cs +++ b/LightlessSync/UI/ContextMenu.cs @@ -90,6 +90,10 @@ internal class ContextMenu : IHostedService if (string.IsNullOrEmpty(target.TargetName) || target.TargetObjectId == 0 || target.TargetHomeWorld.RowId == 0) return; + IPlayerCharacter? targetData = GetPlayerFromObjectTable(target); + if (targetData == null || targetData.Address == IntPtr.Zero) + return; + var world = GetWorld(target.TargetHomeWorld.RowId); if (!IsWorldValid(world)) return; @@ -100,7 +104,7 @@ internal class ContextMenu : IHostedService PrefixChar = 'L', UseDefaultPrefix = false, PrefixColor = 708, - OnClicked = async _ => await HandleSelection(args) + OnClicked = async _ => await HandleSelection(args).ConfigureAwait(false) }); } @@ -115,11 +119,7 @@ internal class ContextMenu : IHostedService try { - var targetData = _objectTable - .OfType() - .FirstOrDefault(p => - string.Equals(p.Name.TextValue, target.TargetName, StringComparison.OrdinalIgnoreCase) && - p.HomeWorld.RowId == target.TargetHomeWorld.RowId); + IPlayerCharacter? targetData = GetPlayerFromObjectTable(target); if (targetData == null || targetData.Address == IntPtr.Zero) { @@ -139,6 +139,15 @@ internal class ContextMenu : IHostedService } } + private IPlayerCharacter? GetPlayerFromObjectTable(MenuTargetDefault target) + { + return _objectTable + .OfType() + .FirstOrDefault(p => + string.Equals(p.Name.TextValue, target.TargetName, StringComparison.OrdinalIgnoreCase) && + p.HomeWorld.RowId == target.TargetHomeWorld.RowId); + } + private World GetWorld(uint worldId) { var sheet = _gameData.GetExcelSheet()!; @@ -162,6 +171,7 @@ internal class ContextMenu : IHostedService return luminaWorlds.FirstOrDefault(x => x.RowId == worldId); } + private static bool IsChineseJapaneseKoreanString(string text) => text.All(IsChineseJapaneseKoreanCharacter); private static bool IsChineseJapaneseKoreanCharacter(char c) => (c >= 0x4E00 && c <= 0x9FFF);