potentially some fixes idk

This commit is contained in:
Stanley Dimant
2023-03-27 10:22:14 +02:00
parent bc8d61b19d
commit 6b35b2bf4a
5 changed files with 78 additions and 44 deletions

View File

@@ -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);
} }

View File

@@ -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);
} }
} }

View File

@@ -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;

View File

@@ -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();

View File

@@ -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();
}
} }