potentially some fixes idk
This commit is contained in:
@@ -24,7 +24,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
|
|||||||
private readonly Func<ObjectKind, Func<nint>, bool, GameObjectHandler> _gameObjectHandlerFactory;
|
private readonly Func<ObjectKind, Func<nint>, bool, GameObjectHandler> _gameObjectHandlerFactory;
|
||||||
private readonly IpcManager _ipcManager;
|
private readonly IpcManager _ipcManager;
|
||||||
private readonly IHostApplicationLifetime _lifetime;
|
private readonly IHostApplicationLifetime _lifetime;
|
||||||
private CancellationTokenSource _applicationCancellationTokenSource = new();
|
private CancellationTokenSource? _applicationCancellationTokenSource = new();
|
||||||
private Guid _applicationId;
|
private Guid _applicationId;
|
||||||
private Task? _applicationTask;
|
private Task? _applicationTask;
|
||||||
private CharacterData _cachedData = new();
|
private CharacterData _cachedData = new();
|
||||||
@@ -158,37 +158,35 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
Guid applicationId = Guid.NewGuid();
|
Guid applicationId = Guid.NewGuid();
|
||||||
_applicationCancellationTokenSource.Cancel();
|
_applicationCancellationTokenSource?.CancelDispose();
|
||||||
_applicationCancellationTokenSource.Dispose();
|
_applicationCancellationTokenSource = null;
|
||||||
_downloadCancellationTokenSource?.Cancel();
|
_downloadCancellationTokenSource?.CancelDispose();
|
||||||
_downloadCancellationTokenSource?.Dispose();
|
|
||||||
_downloadCancellationTokenSource = null;
|
_downloadCancellationTokenSource = null;
|
||||||
_charaHandler?.Dispose();
|
_charaHandler?.Dispose();
|
||||||
_charaHandler = null;
|
_charaHandler = null;
|
||||||
|
|
||||||
if (!_lifetime.ApplicationStopping.IsCancellationRequested)
|
if (_lifetime.ApplicationStopping.IsCancellationRequested) return;
|
||||||
{
|
|
||||||
if (_dalamudUtil.IsZoning)
|
|
||||||
{
|
|
||||||
Logger.LogTrace("[{applicationId}] Removing temp collection for {name} ({OnlineUser})", applicationId, name, OnlineUser);
|
|
||||||
_ipcManager.PenumbraRemoveTemporaryCollection(Logger, applicationId, name);
|
|
||||||
}
|
|
||||||
else if (!_dalamudUtil.IsZoning && !_dalamudUtil.IsInCutscene)
|
|
||||||
{
|
|
||||||
Logger.LogTrace("[{applicationId}] Restoring state for {name} ({OnlineUser})", applicationId, name, OnlineUser);
|
|
||||||
_ipcManager.PenumbraRemoveTemporaryCollection(Logger, applicationId, name);
|
|
||||||
|
|
||||||
foreach (KeyValuePair<ObjectKind, List<FileReplacementData>> item in _cachedData.FileReplacements)
|
if (_dalamudUtil.IsZoning)
|
||||||
|
{
|
||||||
|
Logger.LogTrace("[{applicationId}] Removing temp collection for {name} ({OnlineUser})", applicationId, name, OnlineUser);
|
||||||
|
_ipcManager.PenumbraRemoveTemporaryCollection(Logger, applicationId, name);
|
||||||
|
}
|
||||||
|
else if (_dalamudUtil is { IsZoning: false, IsInCutscene: false })
|
||||||
|
{
|
||||||
|
Logger.LogTrace("[{applicationId}] Restoring state for {name} ({OnlineUser})", applicationId, name, OnlineUser);
|
||||||
|
_ipcManager.PenumbraRemoveTemporaryCollection(Logger, applicationId, name);
|
||||||
|
|
||||||
|
foreach (KeyValuePair<ObjectKind, List<FileReplacementData>> item in _cachedData.FileReplacements)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
try
|
RevertCustomizationData(item.Key, name, applicationId).GetAwaiter().GetResult();
|
||||||
{
|
}
|
||||||
RevertCustomizationData(item.Key, name, applicationId).GetAwaiter().GetResult();
|
catch (InvalidOperationException ex)
|
||||||
}
|
{
|
||||||
catch (InvalidOperationException ex)
|
Logger.LogWarning(ex, "Failed disposing player (not present anymore?)");
|
||||||
{
|
break;
|
||||||
Logger.LogWarning(ex, "Failed disposing player (not present anymore?)");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -381,9 +379,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
|
|||||||
|
|
||||||
var updateModdedPaths = updatedData.Values.Any(v => v.Any(p => p == PlayerChanges.Mods));
|
var updateModdedPaths = updatedData.Values.Any(v => v.Any(p => p == PlayerChanges.Mods));
|
||||||
|
|
||||||
_downloadCancellationTokenSource?.Cancel();
|
_downloadCancellationTokenSource = _downloadCancellationTokenSource?.CancelRecreate();
|
||||||
_downloadCancellationTokenSource?.Dispose();
|
|
||||||
_downloadCancellationTokenSource = new CancellationTokenSource();
|
|
||||||
var downloadToken = _downloadCancellationTokenSource.Token;
|
var downloadToken = _downloadCancellationTokenSource.Token;
|
||||||
|
|
||||||
Task.Run(async () =>
|
Task.Run(async () =>
|
||||||
@@ -421,17 +417,19 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((!_applicationTask?.IsCompleted ?? false) && !downloadToken.IsCancellationRequested && !_applicationCancellationTokenSource.IsCancellationRequested)
|
var appToken = _applicationCancellationTokenSource?.Token;
|
||||||
|
while ((!_applicationTask?.IsCompleted ?? false)
|
||||||
|
&& !downloadToken.IsCancellationRequested
|
||||||
|
&& (!appToken?.IsCancellationRequested ?? false))
|
||||||
{
|
{
|
||||||
// block until current application is done
|
// block until current application is done
|
||||||
Logger.LogDebug("Waiting for current data application (Id: {id}) for player ({handler}) to finish", _applicationId, PlayerName);
|
Logger.LogDebug("Waiting for current data application (Id: {id}) for player ({handler}) to finish", _applicationId, PlayerName);
|
||||||
await Task.Delay(250).ConfigureAwait(false);
|
await Task.Delay(250).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (downloadToken.IsCancellationRequested || _applicationCancellationTokenSource.IsCancellationRequested) return;
|
if (downloadToken.IsCancellationRequested || (appToken?.IsCancellationRequested ?? false)) return;
|
||||||
|
|
||||||
_applicationCancellationTokenSource?.Dispose();
|
_applicationCancellationTokenSource = _applicationCancellationTokenSource.CancelRecreate();
|
||||||
_applicationCancellationTokenSource = new();
|
|
||||||
var token = _applicationCancellationTokenSource.Token;
|
var token = _applicationCancellationTokenSource.Token;
|
||||||
_applicationTask = Task.Run(async () =>
|
_applicationTask = Task.Run(async () =>
|
||||||
{
|
{
|
||||||
@@ -441,7 +439,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
|
|||||||
Logger.LogDebug("[{applicationId}] Starting application task", _applicationId);
|
Logger.LogDebug("[{applicationId}] Starting application task", _applicationId);
|
||||||
|
|
||||||
Logger.LogDebug("[{applicationId}] Waiting for initial draw for for {handler}", _applicationId, _charaHandler);
|
Logger.LogDebug("[{applicationId}] Waiting for initial draw for for {handler}", _applicationId, _charaHandler);
|
||||||
await _dalamudUtil.WaitWhileCharacterIsDrawing(Logger, _charaHandler, _applicationId, 30000, token).ConfigureAwait(false);
|
await _dalamudUtil.WaitWhileCharacterIsDrawing(Logger, _charaHandler!, _applicationId, 30000, token).ConfigureAwait(false);
|
||||||
|
|
||||||
token.ThrowIfCancellationRequested();
|
token.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
@@ -471,9 +469,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
|
|||||||
{
|
{
|
||||||
var player = _dalamudUtil.GetCharacterFromObjectTableByIndex(msg.ObjTblIdx);
|
var player = _dalamudUtil.GetCharacterFromObjectTableByIndex(msg.ObjTblIdx);
|
||||||
if (player == null || !string.Equals(player.Name.ToString(), PlayerName, StringComparison.OrdinalIgnoreCase)) return;
|
if (player == null || !string.Equals(player.Name.ToString(), PlayerName, StringComparison.OrdinalIgnoreCase)) return;
|
||||||
_redrawCts.Cancel();
|
_redrawCts = _redrawCts.CancelRecreate();
|
||||||
_redrawCts.Dispose();
|
|
||||||
_redrawCts = new();
|
|
||||||
_redrawCts.CancelAfter(TimeSpan.FromSeconds(30));
|
_redrawCts.CancelAfter(TimeSpan.FromSeconds(30));
|
||||||
var token = _redrawCts.Token;
|
var token = _redrawCts.Token;
|
||||||
|
|
||||||
@@ -484,7 +480,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
|
|||||||
Logger.LogDebug("Unauthorized character change detected");
|
Logger.LogDebug("Unauthorized character change detected");
|
||||||
await ApplyCustomizationData(applicationId, new(ObjectKind.Player,
|
await ApplyCustomizationData(applicationId, new(ObjectKind.Player,
|
||||||
new HashSet<PlayerChanges>(new[] { PlayerChanges.Palette, PlayerChanges.Customize, PlayerChanges.Heels, PlayerChanges.Mods })),
|
new HashSet<PlayerChanges>(new[] { PlayerChanges.Palette, PlayerChanges.Customize, PlayerChanges.Heels, PlayerChanges.Mods })),
|
||||||
_cachedData, _applicationCancellationTokenSource.Token).ConfigureAwait(false);
|
_cachedData, token).ConfigureAwait(false);
|
||||||
}, token);
|
}, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ public class OnlinePlayerManager : DisposableMediatorSubscriberBase
|
|||||||
|
|
||||||
if (pair.InitializePair(pChar.Name.ToString()))
|
if (pair.InitializePair(pChar.Name.ToString()))
|
||||||
{
|
{
|
||||||
newVisiblePlayers.Add(pair.UserData ?? pair.GroupPair.First().Value.User);
|
newVisiblePlayers.Add(pair.UserData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ public class Pair
|
|||||||
|
|
||||||
public bool CachedPlayerExists => CachedPlayer?.CheckExistence() ?? false;
|
public bool CachedPlayerExists => CachedPlayer?.CheckExistence() ?? false;
|
||||||
public Dictionary<GroupFullInfoDto, GroupPairFullInfoDto> GroupPair { get; set; } = new(GroupDtoComparer.Instance);
|
public Dictionary<GroupFullInfoDto, GroupPairFullInfoDto> GroupPair { get; set; } = new(GroupDtoComparer.Instance);
|
||||||
public bool HasCachedPlayer => CachedPlayer != null && !string.IsNullOrEmpty(CachedPlayer.PlayerName);
|
public bool HasCachedPlayer => CachedPlayer != null && !string.IsNullOrEmpty(CachedPlayer.PlayerName) && _onlineUserIdentDto != null;
|
||||||
public bool IsOnline => CachedPlayer != null;
|
public bool IsOnline => CachedPlayer != null;
|
||||||
|
|
||||||
public bool IsPaused => UserPair != null && UserPair.OtherPermissions.IsPaired() ? UserPair.OtherPermissions.IsPaused() || UserPair.OwnPermissions.IsPaused()
|
public bool IsPaused => UserPair != null && UserPair.OtherPermissions.IsPaired() ? UserPair.OtherPermissions.IsPaused() || UserPair.OwnPermissions.IsPaused()
|
||||||
@@ -44,7 +44,21 @@ public class Pair
|
|||||||
public bool IsVisible => CachedPlayer?.PlayerName != null;
|
public bool IsVisible => CachedPlayer?.PlayerName != null;
|
||||||
public CharacterData? LastReceivedCharacterData { get; set; }
|
public CharacterData? LastReceivedCharacterData { get; set; }
|
||||||
public string? PlayerName => CachedPlayer?.PlayerName ?? string.Empty;
|
public string? PlayerName => CachedPlayer?.PlayerName ?? string.Empty;
|
||||||
public string PlayerNameHash => CachedPlayer?.PlayerNameHash ?? string.Empty;
|
|
||||||
|
public string GetPlayerNameHash()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return CachedPlayer?.PlayerNameHash ?? string.Empty;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogWarning(ex, "Error accessing PlayerNameHash, recreating CachedPlayer");
|
||||||
|
RecreateCachedPlayer();
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
public UserData UserData => UserPair?.User ?? GroupPair.First().Value.User;
|
public UserData UserData => UserPair?.User ?? GroupPair.First().Value.User;
|
||||||
public UserPairDto? UserPair { get; set; }
|
public UserPairDto? UserPair { get; set; }
|
||||||
private CachedPlayer? CachedPlayer { get; set; }
|
private CachedPlayer? CachedPlayer { get; set; }
|
||||||
@@ -138,7 +152,12 @@ public class Pair
|
|||||||
|
|
||||||
public void RecreateCachedPlayer(OnlineUserIdentDto? dto = null)
|
public void RecreateCachedPlayer(OnlineUserIdentDto? dto = null)
|
||||||
{
|
{
|
||||||
if (dto == null && _onlineUserIdentDto == null) return;
|
if (dto == null && _onlineUserIdentDto == null)
|
||||||
|
{
|
||||||
|
CachedPlayer?.Dispose();
|
||||||
|
CachedPlayer = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (dto != null)
|
if (dto != null)
|
||||||
{
|
{
|
||||||
_onlineUserIdentDto = dto;
|
_onlineUserIdentDto = dto;
|
||||||
|
|||||||
@@ -94,10 +94,10 @@ public sealed class PairManager : DisposableMediatorSubscriberBase
|
|||||||
{
|
{
|
||||||
if (pChar == null) return null;
|
if (pChar == null) return null;
|
||||||
var hash = pChar.GetHash256();
|
var hash = pChar.GetHash256();
|
||||||
return GetOnlineUserPairs().Find(p => string.Equals(p.PlayerNameHash, hash, StringComparison.Ordinal));
|
return _allClientPairs.Values.FirstOrDefault(f => string.Equals(hash, f.GetPlayerNameHash()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Pair> GetOnlineUserPairs() => _allClientPairs.Where(p => !string.IsNullOrEmpty(p.Value.PlayerNameHash)).Select(p => p.Value).ToList();
|
public List<Pair> GetOnlineUserPairs() => _allClientPairs.Where(p => !string.IsNullOrEmpty(p.Value.GetPlayerNameHash())).Select(p => p.Value).ToList();
|
||||||
|
|
||||||
public List<UserData> GetVisibleUsers() => _allClientPairs.Where(p => p.Value.HasCachedPlayer).Select(p => p.Key).ToList();
|
public List<UserData> GetVisibleUsers() => _allClientPairs.Where(p => p.Value.HasCachedPlayer).Select(p => p.Key).ToList();
|
||||||
|
|
||||||
|
|||||||
@@ -19,4 +19,23 @@ public static class VariousExtensions
|
|||||||
|
|
||||||
return ((FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject*)gameObject.Address)->ObjectIndex;
|
return ((FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject*)gameObject.Address)->ObjectIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void CancelDispose(this CancellationTokenSource? cts)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
cts?.Cancel();
|
||||||
|
cts?.Dispose();
|
||||||
|
}
|
||||||
|
catch(ObjectDisposedException)
|
||||||
|
{
|
||||||
|
// swallow it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CancellationTokenSource CancelRecreate(this CancellationTokenSource? cts)
|
||||||
|
{
|
||||||
|
cts.CancelDispose();
|
||||||
|
return new CancellationTokenSource();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user