Merge tag '0.9.17' into mare-classic

* tag '0.9.17':
  add census popup on connection
  api update
  census update
  heave fewer redraws as main method for data application, minor fixes
  remove unnecessary exists check
  add visibility for loaded mods size for pair, use menu bar for settings, remove settings button
  fix staging issues
  add download throttling, change header of mare, fix reverting players when going offline/paused when not visible
  use name for glamourer revert
  fix startup breaking
  add inner exception stacktraces
  calc correct button size
  wording
  add permission popup ui
  fix getting identifier during zoning
  indent nonscaled
  remove unnecessary usings
  ui icon boogaloo
  fix cache dict wtf
  add normalized icons
  add owner/moderator/pinned user icons
  check tokentime more precisely in both directions
  more cleanup
  fix sorting and cleanup
  make local groups more usable for pause/resume
  fix outlined font
  rework creation of popout windows into factory and some refactoring in general
  make syncshell admin ui to standalone window
  remove close button on intro ui
  do not allow to open main ui without finishing setup
  readonly bla
  wait for plugin disposal
  fix palette
  wording
  fix palette application and add experimental less redraws option
  some minor fixes
  check for timezone
  idk
  adjust token handling
  fix total user count in syncshell (distinct by UIDs)
  fix text alignment
  fix some shit maybe
  idk some fixes I guess
  fix offset for transfer bar at the bottom, use async collections, clear filter on tab change + add button to clear, require ctrl for align syncshells
  blah
  Some display options for DTR tooltip (#66)
  add ordering
  adjust api to latest
  rework main ui
  add total count on mouseover, make syncshell windows non-blocking
  fix token for character change, add online count to syncshells and groups
  argh
  fix broken font in header
  add more options for the compactui
  fix icons and text of buttons being static in place
  remove logspam
This commit is contained in:
Loporrit
2023-12-08 13:44:18 +00:00
54 changed files with 1646 additions and 743 deletions

View File

@@ -2,11 +2,12 @@
public enum PlayerChanges
{
Heels = 1,
Customize = 2,
Palette = 3,
Honorific = 4,
ModFiles = 5,
ModManip = 6,
Glamourer = 7
ModFiles = 1,
ModManip = 2,
Glamourer = 3,
Customize = 4,
Heels = 5,
Palette = 6,
Honorific = 7,
ForcedRedraw = 8,
}

View File

@@ -48,7 +48,7 @@ public class MareCharaFileManager : DisposableMediatorSubscriberBase
{
if ((await dalamudUtil.RunOnFrameworkThread(() => item.Value.CurrentAddress()).ConfigureAwait(false)) != nint.Zero)
{
await _ipcManager.GlamourerRevert(logger, item.Value, Guid.NewGuid(), cts.Token).ConfigureAwait(false);
await _ipcManager.GlamourerRevert(logger, item.Value.Name, item.Value, Guid.NewGuid(), cts.Token).ConfigureAwait(false);
}
else
{

View File

@@ -1,6 +1,7 @@
using MareSynchronos.API.Dto.User;
using MareSynchronos.FileCache;
using MareSynchronos.Interop;
using MareSynchronos.MareConfiguration;
using MareSynchronos.PlayerData.Handlers;
using MareSynchronos.PlayerData.Pairs;
using MareSynchronos.Services;
@@ -20,12 +21,13 @@ public class PairHandlerFactory
private readonly IpcManager _ipcManager;
private readonly ILoggerFactory _loggerFactory;
private readonly MareMediator _mareMediator;
private readonly MareConfigService _mareConfigService;
private readonly PluginWarningNotificationService _pluginWarningNotificationManager;
public PairHandlerFactory(ILoggerFactory loggerFactory, GameObjectHandlerFactory gameObjectHandlerFactory, IpcManager ipcManager,
FileDownloadManagerFactory fileDownloadManagerFactory, DalamudUtilService dalamudUtilService,
PluginWarningNotificationService pluginWarningNotificationManager, IHostApplicationLifetime hostApplicationLifetime,
FileCacheManager fileCacheManager, MareMediator mareMediator)
FileCacheManager fileCacheManager, MareMediator mareMediator, MareConfigService mareConfigService)
{
_loggerFactory = loggerFactory;
_gameObjectHandlerFactory = gameObjectHandlerFactory;
@@ -36,12 +38,13 @@ public class PairHandlerFactory
_hostApplicationLifetime = hostApplicationLifetime;
_fileCacheManager = fileCacheManager;
_mareMediator = mareMediator;
_mareConfigService = mareConfigService;
}
public PairHandler Create(OnlineUserIdentDto onlineUserIdentDto)
{
return new PairHandler(_loggerFactory.CreateLogger<PairHandler>(), onlineUserIdentDto, _gameObjectHandlerFactory,
_ipcManager, _fileDownloadManagerFactory.Create(), _pluginWarningNotificationManager, _dalamudUtilService, _hostApplicationLifetime,
_fileCacheManager, _mareMediator);
_fileCacheManager, _mareMediator, _mareConfigService);
}
}

View File

@@ -22,6 +22,7 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase
private bool _haltProcessing = false;
private bool _ignoreSendAfterRedraw = false;
private int _ptrNullCounter = 0;
private byte _classJob = 0;
private CancellationTokenSource _zoningCts = new();
public GameObjectHandler(ILogger<GameObjectHandler> logger, PerformanceCollectorService performanceCollector,
@@ -98,6 +99,10 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase
ModelFilesInSlotLoaded
}
public byte RaceId { get; private set; }
public byte Gender { get; private set; }
public byte TribeId { get; private set; }
public IntPtr Address { get; private set; }
public string Name { get; private set; }
public ObjectKind ObjectKind { get; }
@@ -215,6 +220,14 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase
if (((DrawObject*)DrawObjectAddress)->Object.GetObjectType() == ObjectType.CharacterBase
&& ((CharacterBase*)DrawObjectAddress)->GetModelType() == CharacterBase.ModelType.Human)
{
var classJob = chara->CharacterData.ClassJob;
if (classJob != _classJob)
{
Logger.LogTrace("[{this}] classjob changed from {old} to {new}", this, _classJob, classJob);
_classJob = classJob;
Mediator.Publish(new ClassJobChangedMessage(this));
}
equipDiff = CompareAndUpdateEquipByteData((byte*)&((Human*)DrawObjectAddress)->Head);
ref var mh = ref chara->DrawData.Weapon(WeaponSlot.MainHand);
@@ -244,6 +257,19 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase
if (((DrawObject*)DrawObjectAddress)->Object.GetObjectType() == ObjectType.CharacterBase
&& ((CharacterBase*)DrawObjectAddress)->GetModelType() == CharacterBase.ModelType.Human)
{
var gender = ((Human*)DrawObjectAddress)->Customize.Sex;
var raceId = ((Human*)DrawObjectAddress)->Customize.Race;
var tribeId = ((Human*)DrawObjectAddress)->Customize.Clan;
if (_isOwnedObject && ObjectKind == ObjectKind.Player
&& (gender != Gender || raceId != RaceId || tribeId != TribeId))
{
Mediator.Publish(new CensusUpdateMessage(gender, raceId, tribeId));
Gender = gender;
RaceId = raceId;
TribeId = tribeId;
}
customizeDiff = CompareAndUpdateCustomizeData(((Human*)DrawObjectAddress)->Customize.Data);
if (customizeDiff)
Logger.LogTrace("Checking [{this}] customize data as human from draw obj, result: {diff}", this, customizeDiff);

View File

@@ -2,6 +2,7 @@
using MareSynchronos.API.Dto.User;
using MareSynchronos.FileCache;
using MareSynchronos.Interop;
using MareSynchronos.MareConfiguration;
using MareSynchronos.PlayerData.Factories;
using MareSynchronos.PlayerData.Pairs;
using MareSynchronos.Services;
@@ -21,6 +22,7 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase
private readonly DalamudUtilService _dalamudUtil;
private readonly FileDownloadManager _downloadManager;
private readonly FileCacheManager _fileDbManager;
private readonly MareConfigService _mareConfigService;
private readonly GameObjectHandlerFactory _gameObjectHandlerFactory;
private readonly IpcManager _ipcManager;
private readonly IHostApplicationLifetime _lifetime;
@@ -34,13 +36,16 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase
private bool _forceApplyMods = false;
private bool _isVisible;
private string _penumbraCollection;
private bool _redrawOnNextApplication = false;
public long LastAppliedDataSize { get; private set; }
public PairHandler(ILogger<PairHandler> logger, OnlineUserIdentDto onlineUser,
GameObjectHandlerFactory gameObjectHandlerFactory,
IpcManager ipcManager, FileDownloadManager transferManager,
PluginWarningNotificationService pluginWarningNotificationManager,
DalamudUtilService dalamudUtil, IHostApplicationLifetime lifetime,
FileCacheManager fileDbManager, MareMediator mediator) : base(logger, mediator)
FileCacheManager fileDbManager, MareMediator mediator,
MareConfigService mareConfigService) : base(logger, mediator)
{
OnlineUser = onlineUser;
_gameObjectHandlerFactory = gameObjectHandlerFactory;
@@ -50,7 +55,7 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase
_dalamudUtil = dalamudUtil;
_lifetime = lifetime;
_fileDbManager = fileDbManager;
_mareConfigService = mareConfigService;
_penumbraCollection = _ipcManager.PenumbraCreateTemporaryCollectionAsync(logger, OnlineUser.User.UID).ConfigureAwait(false).GetAwaiter().GetResult();
Mediator.Subscribe<FrameworkUpdateMessage>(this, (_) => FrameworkUpdate());
@@ -70,6 +75,15 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase
_charaHandler = null;
}
});
Mediator.Subscribe<ClassJobChangedMessage>(this, (msg) =>
{
if (msg.gameObjectHandler == _charaHandler)
{
_redrawOnNextApplication = true;
}
});
LastAppliedDataSize = -1;
}
public bool IsVisible
@@ -127,6 +141,12 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase
_forceApplyMods = false;
}
if (_redrawOnNextApplication && charaDataToUpdate.TryGetValue(ObjectKind.Player, out var player))
{
player.Add(PlayerChanges.ForcedRedraw);
_redrawOnNextApplication = false;
}
if (charaDataToUpdate.TryGetValue(ObjectKind.Player, out var playerChanges))
{
_pluginWarningNotificationManager.NotifyForMissingPlugins(OnlineUser.User, PlayerName!, playerChanges);
@@ -173,22 +193,35 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase
if (_lifetime.ApplicationStopping.IsCancellationRequested) return;
if (_dalamudUtil is { IsZoning: false, IsInCutscene: false })
if (_dalamudUtil is { IsZoning: false, IsInCutscene: false } && !string.IsNullOrEmpty(name))
{
Logger.LogTrace("[{applicationId}] Restoring state for {name} ({OnlineUser})", applicationId, name, OnlineUser);
Logger.LogDebug("[{applicationId}] Removing Temp Collection for {name} ({user})", applicationId, name, OnlineUser);
_ipcManager.PenumbraRemoveTemporaryCollectionAsync(Logger, applicationId, _penumbraCollection).GetAwaiter().GetResult();
foreach (KeyValuePair<ObjectKind, List<FileReplacementData>> item in _cachedData?.FileReplacements ?? [])
if (!IsVisible)
{
try
Logger.LogDebug("[{applicationId}] Restoring Glamourer for {name} ({user})", applicationId, name, OnlineUser);
_ipcManager.GlamourerRevertByNameAsync(Logger, name, applicationId).GetAwaiter().GetResult();
}
else
{
var cts = new CancellationTokenSource();
cts.CancelAfter(TimeSpan.FromSeconds(60));
foreach (KeyValuePair<ObjectKind, List<FileReplacementData>> item in _cachedData?.FileReplacements ?? [])
{
RevertCustomizationDataAsync(item.Key, name, applicationId).GetAwaiter().GetResult();
}
catch (InvalidOperationException ex)
{
Logger.LogWarning(ex, "Failed disposing player (not present anymore?)");
break;
try
{
RevertCustomizationDataAsync(item.Key, name, applicationId, cts.Token).GetAwaiter().GetResult();
}
catch (InvalidOperationException ex)
{
Logger.LogWarning(ex, "Failed disposing player (not present anymore?)");
break;
}
}
cts.CancelDispose();
}
}
}
@@ -263,15 +296,15 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase
}
break;
case PlayerChanges.ModFiles:
case PlayerChanges.ModManip:
case PlayerChanges.ForcedRedraw:
await _ipcManager.PenumbraRedrawAsync(Logger, handler, applicationId, token).ConfigureAwait(false);
break;
default:
break;
}
token.ThrowIfCancellationRequested();
}
if (changes.Value.Contains(PlayerChanges.ModFiles) || changes.Value.Contains(PlayerChanges.ModManip) || changes.Value.Contains(PlayerChanges.Glamourer))
await _ipcManager.PenumbraRedrawAsync(Logger, handler, applicationId, token).ConfigureAwait(false);
}
finally
{
@@ -361,6 +394,11 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase
if (updateModdedPaths)
{
await _ipcManager.PenumbraSetTemporaryModsAsync(Logger, _applicationId, _penumbraCollection, moddedPaths).ConfigureAwait(false);
LastAppliedDataSize = -1;
foreach (var path in moddedPaths.Select(v => new FileInfo(v.Value)).Where(p => p.Exists))
{
LastAppliedDataSize += path.Length;
}
}
if (updateManip)
@@ -453,14 +491,11 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase
_ipcManager.PenumbraAssignTemporaryCollectionAsync(Logger, _penumbraCollection, _charaHandler.GetGameObject()!.ObjectIndex).GetAwaiter().GetResult();
}
private async Task RevertCustomizationDataAsync(ObjectKind objectKind, string name, Guid applicationId)
private async Task RevertCustomizationDataAsync(ObjectKind objectKind, string name, Guid applicationId, CancellationToken cancelToken)
{
nint address = _dalamudUtil.GetPlayerCharacterFromCachedTableByIdent(OnlineUser.Ident);
if (address == nint.Zero) return;
var cancelToken = new CancellationTokenSource();
cancelToken.CancelAfter(TimeSpan.FromSeconds(60));
Logger.LogDebug("[{applicationId}] Reverting all Customization for {alias}/{name} {objectKind}", applicationId, OnlineUser.User.AliasOrUID, name, objectKind);
if (objectKind == ObjectKind.Player)
@@ -468,7 +503,7 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase
using GameObjectHandler tempHandler = await _gameObjectHandlerFactory.Create(ObjectKind.Player, () => address, isWatched: false).ConfigureAwait(false);
tempHandler.CompareNameAndThrow(name);
Logger.LogDebug("[{applicationId}] Restoring Customization and Equipment for {alias}/{name}", applicationId, OnlineUser.User.AliasOrUID, name);
await _ipcManager.GlamourerRevert(Logger, tempHandler, applicationId, cancelToken.Token).ConfigureAwait(false);
await _ipcManager.GlamourerRevert(Logger, name, tempHandler, applicationId, cancelToken).ConfigureAwait(false);
tempHandler.CompareNameAndThrow(name);
Logger.LogDebug("[{applicationId}] Restoring Heels for {alias}/{name}", applicationId, OnlineUser.User.AliasOrUID, name);
await _ipcManager.HeelsRestoreOffsetForPlayerAsync(address).ConfigureAwait(false);
@@ -489,8 +524,8 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase
{
await _ipcManager.CustomizePlusRevertAsync(minionOrMount).ConfigureAwait(false);
using GameObjectHandler tempHandler = await _gameObjectHandlerFactory.Create(ObjectKind.MinionOrMount, () => minionOrMount, isWatched: false).ConfigureAwait(false);
await _ipcManager.GlamourerRevert(Logger, tempHandler, applicationId, cancelToken.Token).ConfigureAwait(false);
await _ipcManager.PenumbraRedrawAsync(Logger, tempHandler, applicationId, cancelToken.Token).ConfigureAwait(false);
await _ipcManager.GlamourerRevert(Logger, tempHandler.Name, tempHandler, applicationId, cancelToken).ConfigureAwait(false);
await _ipcManager.PenumbraRedrawAsync(Logger, tempHandler, applicationId, cancelToken).ConfigureAwait(false);
}
}
else if (objectKind == ObjectKind.Pet)
@@ -500,8 +535,8 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase
{
await _ipcManager.CustomizePlusRevertAsync(pet).ConfigureAwait(false);
using GameObjectHandler tempHandler = await _gameObjectHandlerFactory.Create(ObjectKind.Pet, () => pet, isWatched: false).ConfigureAwait(false);
await _ipcManager.GlamourerRevert(Logger, tempHandler, applicationId, cancelToken.Token).ConfigureAwait(false);
await _ipcManager.PenumbraRedrawAsync(Logger, tempHandler, applicationId, cancelToken.Token).ConfigureAwait(false);
await _ipcManager.GlamourerRevert(Logger, tempHandler.Name, tempHandler, applicationId, cancelToken).ConfigureAwait(false);
await _ipcManager.PenumbraRedrawAsync(Logger, tempHandler, applicationId, cancelToken).ConfigureAwait(false);
}
}
else if (objectKind == ObjectKind.Companion)
@@ -511,12 +546,10 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase
{
await _ipcManager.CustomizePlusRevertAsync(companion).ConfigureAwait(false);
using GameObjectHandler tempHandler = await _gameObjectHandlerFactory.Create(ObjectKind.Pet, () => companion, isWatched: false).ConfigureAwait(false);
await _ipcManager.GlamourerRevert(Logger, tempHandler, applicationId, cancelToken.Token).ConfigureAwait(false);
await _ipcManager.PenumbraRedrawAsync(Logger, tempHandler, applicationId, cancelToken.Token).ConfigureAwait(false);
await _ipcManager.GlamourerRevert(Logger, tempHandler.Name, tempHandler, applicationId, cancelToken).ConfigureAwait(false);
await _ipcManager.PenumbraRedrawAsync(Logger, tempHandler, applicationId, cancelToken).ConfigureAwait(false);
}
}
cancelToken.CancelDispose();
}
private List<FileReplacementData> TryCalculateModdedDictionary(Guid applicationBase, CharacterData charaData, out Dictionary<string, string> moddedDictionary, CancellationToken token)

View File

@@ -44,6 +44,7 @@ public class Pair
public bool IsVisible => CachedPlayer?.IsVisible ?? false;
public CharacterData? LastReceivedCharacterData { get; set; }
public string? PlayerName => CachedPlayer?.PlayerName ?? string.Empty;
public long LastAppliedDataSize => CachedPlayer?.LastAppliedDataSize ?? -1;
public UserData UserData => UserPair?.User ?? GroupPair.First().Value.User;
@@ -58,9 +59,11 @@ public class Pair
SeStringBuilder seStringBuilder = new();
SeStringBuilder seStringBuilder2 = new();
SeStringBuilder seStringBuilder3 = new();
SeStringBuilder seStringBuilder4 = new();
var openProfileSeString = seStringBuilder.AddUiForeground(526).AddText(" ").AddUiForegroundOff().AddText("Open Profile").Build();
var reapplyDataSeString = seStringBuilder2.AddUiForeground(526).AddText(" ").AddUiForegroundOff().AddText("Reapply last data").Build();
var cyclePauseState = seStringBuilder3.AddUiForeground(526).AddText(" ").AddUiForegroundOff().AddText("Cycle pause state").Build();
var changePermissions = seStringBuilder4.AddUiForeground(526).AddText(" ").AddUiForegroundOff().AddText("Change Permissions").Build();
args.AddCustomItem(new GameObjectContextMenuItem(openProfileSeString, (a) =>
{
_mediator.Publish(new ProfileOpenStandaloneMessage(this));
@@ -69,6 +72,10 @@ public class Pair
{
ApplyLastReceivedData(forced: true);
}, useDalamudIndicator: false));
args.AddCustomItem(new GameObjectContextMenuItem(changePermissions, (a) =>
{
_mediator.Publish(new OpenPermissionWindow(this));
}, useDalamudIndicator: false));
args.AddCustomItem(new GameObjectContextMenuItem(cyclePauseState, (a) =>
{
_mediator.Publish(new CyclePauseMessage(UserData));