Merge tag '0.9.21' into mare-classic

* tag '0.9.21':
  fix combat situations not redrawing every time after combat ends
  add more resilience to MCDF export and loading
  disable data application and scanner in combat
  fix bug
  add lock around adding to cached handled paths
  disable target in pvp
  add click to target in ui
  change tooltip for penumbra version to 0.8.2.1
  add file storage validation
  add experimental resolving of data through penumbra
  adjust initial dialog to opt in/out into census with buttons
This commit is contained in:
Loporrit
2023-12-09 12:06:10 +00:00
23 changed files with 352 additions and 129 deletions

View File

@@ -66,13 +66,18 @@ public class DrawUserPair : DrawPairBase
ImGui.SetCursorPosY(textPosY);
ImGui.PushFont(UiBuilder.IconFont);
UiSharedService.ColorText(FontAwesomeIcon.Eye.ToIconString(), ImGuiColors.ParsedGreen);
if (ImGui.IsItemClicked())
{
_mediator.Publish(new TargetPairMessage(_pair));
}
ImGui.PopFont();
var visibleTooltip = _pair.UserData.AliasOrUID + " is visible: " + _pair.PlayerName!;
var visibleTooltip = _pair.UserData.AliasOrUID + " is visible: " + _pair.PlayerName! + Environment.NewLine + "Click to target this player";
if (_pair.LastAppliedDataSize >= 0)
{
visibleTooltip += UiSharedService.TooltipSeparator +
"Loaded Mods Size: " + UiSharedService.ByteToString(_pair.LastAppliedDataSize, true);
}
UiSharedService.AttachToolTip(visibleTooltip);
}
}

View File

@@ -22,6 +22,8 @@ public class BanUserPopupHandler : IPopupHandler
public Vector2 PopupSize => new(500, 250);
public bool ShowClose => true;
public void DrawContent()
{
UiSharedService.TextWrapped("User " + (_reportedPair.UserData.AliasOrUID) + " will be banned and removed from this Syncshell.");
@@ -37,10 +39,6 @@ public class BanUserPopupHandler : IPopupHandler
UiSharedService.TextWrapped("The reason will be displayed in the banlist. The current server-side alias if present (Vanity ID) will automatically be attached to the reason.");
}
public void OnClose()
{
}
public void Open(OpenBanUserPopupMessage message)
{
_reportedPair = message.PairToBan;

View File

@@ -5,8 +5,7 @@ namespace MareSynchronos.UI.Components.Popup;
public interface IPopupHandler
{
Vector2 PopupSize { get; }
bool ShowClose { get; }
void DrawContent();
void OnClose();
}

View File

@@ -62,17 +62,13 @@ public class PopupHandler : WindowMediatorSubscriberBase
using var popup = ImRaii.Popup(WindowName, ImGuiWindowFlags.Modal);
if (!popup) return;
_currentHandler.DrawContent();
ImGui.Separator();
if (UiSharedService.NormalizedIconTextButton(FontAwesomeIcon.Times, "Close"))
if (_currentHandler.ShowClose)
{
ImGui.CloseCurrentPopup();
_currentHandler.OnClose();
ImGui.Separator();
if (UiSharedService.NormalizedIconTextButton(FontAwesomeIcon.Times, "Close"))
{
ImGui.CloseCurrentPopup();
}
}
}
public override void OnClose()
{
base.OnClose();
_currentHandler?.OnClose();
}
}

View File

@@ -24,6 +24,8 @@ internal class ReportPopupHandler : IPopupHandler
public Vector2 PopupSize => new(500, 500);
public bool ShowClose => true;
public void DrawContent()
{
using (ImRaii.PushFont(_uiSharedService.UidFont))
@@ -49,10 +51,6 @@ internal class ReportPopupHandler : IPopupHandler
}
}
public void OnClose()
{
}
public void Open(OpenReportPopupMessage msg)
{
_reportedPair = msg.PairToReport;

View File

@@ -15,6 +15,8 @@ public class GposeUi : WindowMediatorSubscriberBase
private readonly DalamudUtilService _dalamudUtil;
private readonly FileDialogManager _fileDialogManager;
private readonly MareCharaFileManager _mareCharaFileManager;
private Task<long>? _expectedLength;
private Task? _applicationTask;
public GposeUi(ILogger<GposeUi> logger, MareCharaFileManager mareCharaFileManager,
DalamudUtilService dalamudUtil, FileDialogManager fileDialogManager, MareConfigService configService,
@@ -51,21 +53,28 @@ public class GposeUi : WindowMediatorSubscriberBase
_configService.Current.ExportFolder = Path.GetDirectoryName(path) ?? string.Empty;
_configService.Save();
_ = Task.Run(() => _mareCharaFileManager.LoadMareCharaFile(path));
_expectedLength = Task.Run(() => _mareCharaFileManager.LoadMareCharaFile(path));
}, 1, Directory.Exists(_configService.Current.ExportFolder) ? _configService.Current.ExportFolder : null);
}
UiSharedService.AttachToolTip("Applies it to the currently selected GPose actor");
if (_mareCharaFileManager.LoadedCharaFile != null)
if (_mareCharaFileManager.LoadedCharaFile != null && _expectedLength != null)
{
UiSharedService.TextWrapped("Loaded file: " + _mareCharaFileManager.LoadedCharaFile.FilePath);
UiSharedService.TextWrapped("File Description: " + _mareCharaFileManager.LoadedCharaFile.CharaFileData.Description);
if (UiSharedService.NormalizedIconTextButton(FontAwesomeIcon.Check, "Apply loaded MCDF"))
{
_ = Task.Run(async () => await _mareCharaFileManager.ApplyMareCharaFile(_dalamudUtil.GposeTargetGameObject).ConfigureAwait(false));
_applicationTask = Task.Run(async () => await _mareCharaFileManager.ApplyMareCharaFile(_dalamudUtil.GposeTargetGameObject, _expectedLength!.GetAwaiter().GetResult()).ConfigureAwait(false));
}
UiSharedService.AttachToolTip("Applies it to the currently selected GPose actor");
UiSharedService.ColorTextWrapped("Warning: redrawing or changing the character will revert all applied mods.", ImGuiColors.DalamudYellow);
}
if (_applicationTask?.IsFaulted ?? false)
{
UiSharedService.ColorTextWrapped("Failure to read MCDF file. MCDF file is possibly corrupt. Re-export the MCDF file and try again.",
ImGuiColors.DalamudRed);
UiSharedService.ColorTextWrapped("Note: if this is your MCDF, try redrawing yourself, wait and re-export the file. " +
"If you received it from someone else have them do the same.", ImGuiColors.DalamudYellow);
}
}
else
{
@@ -77,6 +86,8 @@ public class GposeUi : WindowMediatorSubscriberBase
private void EndGpose()
{
IsOpen = false;
_applicationTask = null;
_expectedLength = null;
_mareCharaFileManager.ClearMareCharaFile();
}

View File

@@ -35,6 +35,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
private readonly FileCompactor _fileCompactor;
private readonly FileUploadManager _fileTransferManager;
private readonly FileTransferOrchestrator _fileTransferOrchestrator;
private readonly FileCacheManager _fileCacheManager;
private readonly MareCharaFileManager _mareCharaFileManager;
private readonly PairManager _pairManager;
private readonly PerformanceCollectorService _performanceCollector;
@@ -49,6 +50,11 @@ public class SettingsUi : WindowMediatorSubscriberBase
private bool _readClearCache = false;
private bool _readExport = false;
private bool _wasOpen = false;
private readonly IProgress<(int, int, FileCacheEntity)> _validationProgress;
private Task<List<FileCacheEntity>>? _validationTask;
private CancellationTokenSource? _validationCts;
private (int, int, FileCacheEntity) _currentProgress;
private Task? _exportTask;
public SettingsUi(ILogger<SettingsUi> logger,
UiSharedService uiShared, MareConfigService configService,
@@ -57,6 +63,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
MareMediator mediator, PerformanceCollectorService performanceCollector,
FileUploadManager fileTransferManager,
FileTransferOrchestrator fileTransferOrchestrator,
FileCacheManager fileCacheManager,
FileCompactor fileCompactor, ApiController apiController) : base(logger, mediator, "Mare Synchronos Settings")
{
_configService = configService;
@@ -66,11 +73,13 @@ public class SettingsUi : WindowMediatorSubscriberBase
_performanceCollector = performanceCollector;
_fileTransferManager = fileTransferManager;
_fileTransferOrchestrator = fileTransferOrchestrator;
_fileCacheManager = fileCacheManager;
_apiController = apiController;
_fileCompactor = fileCompactor;
_uiShared = uiShared;
AllowClickthrough = false;
AllowPinning = false;
_validationProgress = new Progress<(int, int, FileCacheEntity)>(v => _currentProgress = v);
SizeConstraints = new WindowSizeConstraints()
{
@@ -431,17 +440,11 @@ public class SettingsUi : WindowMediatorSubscriberBase
_configService.Current.ExportFolder = Path.GetDirectoryName(path) ?? string.Empty;
_configService.Save();
_ = Task.Run(() =>
_exportTask = Task.Run(() =>
{
try
{
_mareCharaFileManager.SaveMareCharaFile(LastCreatedCharacterData, _exportDescription, path);
_exportDescription = string.Empty;
}
catch (Exception ex)
{
_logger.LogCritical(ex, "Error saving data");
}
var desc = _exportDescription;
_exportDescription = string.Empty;
_mareCharaFileManager.SaveMareCharaFile(LastCreatedCharacterData, desc, path);
});
}, Directory.Exists(_configService.Current.ExportFolder) ? _configService.Current.ExportFolder : null);
}
@@ -453,6 +456,11 @@ public class SettingsUi : WindowMediatorSubscriberBase
UiSharedService.ColorTextWrapped("Export in progress", ImGuiColors.DalamudYellow);
}
if (_exportTask?.IsFaulted ?? false)
{
UiSharedService.ColorTextWrapped("Export failed, check /xllog for more details.", ImGuiColors.DalamudRed);
}
ImGui.Unindent();
}
bool openInGpose = _configService.Current.OpenGposeImportOnGposeStart;
@@ -509,6 +517,49 @@ public class SettingsUi : WindowMediatorSubscriberBase
ImGui.EndDisabled();
ImGui.TextUnformatted("The file compactor is only available on Windows.");
}
ImGuiHelpers.ScaledDummy(new Vector2(10, 10));
ImGui.Separator();
UiSharedService.TextWrapped("File Storage validation can make sure that all files in your local Mare Storage are valid. " +
"Run the validation before you clear the Storage for no reason. " + Environment.NewLine +
"This operation, depending on how many files you have in your storage, can take a while and will be CPU and drive intensive.");
using (ImRaii.Disabled(_validationTask != null && !_validationTask.IsCompleted))
{
if (UiSharedService.NormalizedIconTextButton(FontAwesomeIcon.Check, "Start File Storage Validation"))
{
_validationCts?.Cancel();
_validationCts?.Dispose();
_validationCts = new();
var token = _validationCts.Token;
_validationTask = Task.Run(() => _fileCacheManager.ValidateLocalIntegrity(_validationProgress, token));
}
}
if (_validationTask != null && !_validationTask.IsCompleted)
{
ImGui.SameLine();
if (UiSharedService.NormalizedIconTextButton(FontAwesomeIcon.Times, "Cancel"))
{
_validationCts?.Cancel();
}
}
if (_validationTask != null)
{
using (ImRaii.PushIndent(20f))
{
if (_validationTask.IsCompleted)
{
UiSharedService.TextWrapped($"The storage validation has completed and removed {_validationTask.Result.Count} invalid files from storage.");
}
else
{
UiSharedService.TextWrapped($"Storage validation is running: {_currentProgress.Item1}/{_currentProgress.Item2}");
UiSharedService.TextWrapped($"Current item: {_currentProgress.Item3.ResolvedFilepath}");
}
}
}
ImGui.Separator();
ImGuiHelpers.ScaledDummy(new Vector2(10, 10));
ImGui.TextUnformatted("To clear the local storage accept the following disclaimer");
@@ -549,6 +600,16 @@ public class SettingsUi : WindowMediatorSubscriberBase
}
_lastTab = "General";
UiSharedService.FontText("Experimental", _uiShared.UidFont);
var usePenumbraResolve = _configService.Current.ExperimentalUsePenumbraResourceTree;
if (ImGui.Checkbox("Use Penumbra to resolve character", ref usePenumbraResolve))
{
_configService.Current.ExperimentalUsePenumbraResourceTree = usePenumbraResolve;
_configService.Save();
}
UiSharedService.DrawHelpText("Requires Penumbra version greater equal to 0.8.2.1 - please report issues with that feature to the Penumbra Discord");
ImGui.Separator();
UiSharedService.FontText("Notes", _uiShared.UidFont);
if (UiSharedService.NormalizedIconTextButton(FontAwesomeIcon.StickyNote, "Export all your user notes to clipboard"))
{