0.4.2: fix heels integration, potentially fix crashes, delay handling of transient resource loads, change transients to concurrent dictionary

This commit is contained in:
Stanley Dimant
2022-09-11 01:23:41 +02:00
parent 23f01bc50c
commit a618fad7d9
8 changed files with 142 additions and 84 deletions

View File

@@ -117,6 +117,17 @@ public class CachedPlayer
continue;
}
}
if (objectKind == ObjectKind.Player)
{
bool heelsOffsetDifferent = _cachedData.HeelsOffset != characterData.HeelsOffset;
if (heelsOffsetDifferent)
{
Logger.Debug("Updating " + objectKind);
charaDataToUpdate.Add(objectKind);
continue;
}
}
}
_cachedData = characterData;
@@ -324,6 +335,7 @@ public class CachedPlayer
{
_ipcManager.GlamourerApplyOnlyCustomization(_originalGlamourerData, PlayerCharacter);
_ipcManager.GlamourerApplyOnlyEquipment(_lastGlamourerData, PlayerCharacter);
_ipcManager.HeelsRestoreOffsetForPlayer(PlayerCharacter);
}
else
{

View File

@@ -207,16 +207,30 @@ namespace MareSynchronos.Managers
});
}
public void HeelsRestoreOffsetForPlayer(IntPtr character)
{
if (!CheckHeelsApi()) return;
actionQueue.Enqueue(() =>
{
var gameObj = _dalamudUtil.CreateGameObject(character);
if (gameObj != null)
{
Logger.Verbose("Restoring Heels data to " + character.ToString("X"));
_heelsUnregisterPlayer.InvokeAction(gameObj);
}
});
}
public void GlamourerApplyAll(string? customization, IntPtr obj)
{
if (!CheckGlamourerApi() || string.IsNullOrEmpty(customization)) return;
actionQueue.Enqueue(() =>
{
var gameObj = _dalamudUtil.CreateGameObject(obj);
if (gameObj != null)
if (gameObj is Character c)
{
Logger.Verbose("Glamourer applying for " + gameObj);
_glamourerApplyAll!.InvokeAction(customization, gameObj);
Logger.Verbose("Glamourer applying for " + c.Address.ToString("X"));
_glamourerApplyAll!.InvokeAction(customization, c);
}
});
}
@@ -227,10 +241,10 @@ namespace MareSynchronos.Managers
actionQueue.Enqueue(() =>
{
var gameObj = _dalamudUtil.CreateGameObject(character);
if (gameObj != null)
if (gameObj is Character c)
{
Logger.Verbose("Glamourer apply only equipment to " + character.ToString("X"));
_glamourerApplyOnlyEquipment!.InvokeAction(customization, gameObj);
Logger.Verbose("Glamourer apply only equipment to " + c.Address.ToString("X"));
_glamourerApplyOnlyEquipment!.InvokeAction(customization, c);
}
});
}
@@ -241,10 +255,10 @@ namespace MareSynchronos.Managers
actionQueue.Enqueue(() =>
{
var gameObj = _dalamudUtil.CreateGameObject(character);
if (gameObj != null)
if (gameObj is Character c)
{
Logger.Verbose("Glamourer apply only customization to " + character.ToString("X"));
_glamourerApplyOnlyCustomization!.InvokeAction(customization, gameObj);
Logger.Verbose("Glamourer apply only customization to " + c.Address.ToString("X"));
_glamourerApplyOnlyCustomization!.InvokeAction(customization, c);
}
});
}
@@ -255,9 +269,9 @@ namespace MareSynchronos.Managers
try
{
var gameObj = _dalamudUtil.CreateGameObject(character);
if (gameObj != null)
if (gameObj is Character c)
{
var glamourerString = _glamourerGetAllCustomization!.InvokeFunc(gameObj);
var glamourerString = _glamourerGetAllCustomization!.InvokeFunc(c);
byte[] bytes = Convert.FromBase64String(glamourerString);
// ignore transparency
bytes[88] = 128;

View File

@@ -28,6 +28,7 @@ namespace MareSynchronos.Managers
private readonly Dictionary<ObjectKind, Func<bool>> objectKindsToUpdate = new();
private CancellationTokenSource? _playerChangedCts = new();
private CancellationTokenSource _transientUpdateCts = new();
private List<PlayerRelatedObject> playerRelatedObjects = new List<PlayerRelatedObject>();
@@ -69,8 +70,19 @@ namespace MareSynchronos.Managers
{
if (obj.Address == gameObj && !obj.HasUnprocessedUpdate)
{
obj.HasUnprocessedUpdate = true;
OnPlayerOrAttachedObjectsChanged();
_transientUpdateCts.Cancel();
_transientUpdateCts = new CancellationTokenSource();
var token = _transientUpdateCts.Token;
Task.Run(async () =>
{
Logger.Debug("Delaying transient resource load update");
await Task.Delay(750, token);
if (obj.HasUnprocessedUpdate || token.IsCancellationRequested) return;
Logger.Debug("Firing transient resource load update");
obj.HasTransientsUpdate = true;
OnPlayerOrAttachedObjectsChanged();
}, token);
return;
}
}
@@ -82,7 +94,7 @@ namespace MareSynchronos.Managers
if (LastCreatedCharacterData != null && LastCreatedCharacterData.HeelsOffset != change && !player.IsProcessing)
{
Logger.Debug("Heels offset changed to " + change);
playerRelatedObjects.First(f => f.ObjectKind == ObjectKind.Player).HasUnprocessedUpdate = true;
playerRelatedObjects.First(f => f.ObjectKind == ObjectKind.Player).HasTransientsUpdate = true;
}
}
@@ -129,14 +141,15 @@ namespace MareSynchronos.Managers
private async Task<CharacterCacheDto?> CreateFullCharacterCacheDto(CancellationToken token)
{
foreach (var unprocessedObject in playerRelatedObjects.Where(c => c.HasUnprocessedUpdate).ToList())
foreach (var unprocessedObject in playerRelatedObjects.Where(c => c.HasUnprocessedUpdate || c.HasTransientsUpdate).ToList())
{
Logger.Verbose("Building Cache for " + unprocessedObject.ObjectKind);
PermanentDataCache = _characterDataFactory.BuildCharacterData(PermanentDataCache, unprocessedObject.ObjectKind, unprocessedObject.Address, token);
PermanentDataCache = _characterDataFactory.BuildCharacterData(PermanentDataCache, unprocessedObject, token);
if (!token.IsCancellationRequested)
{
unprocessedObject.HasUnprocessedUpdate = false;
unprocessedObject.IsProcessing = false;
unprocessedObject.HasTransientsUpdate = false;
}
token.ThrowIfCancellationRequested();
}
@@ -165,7 +178,6 @@ namespace MareSynchronos.Managers
if (address == item.Address)
{
Logger.Debug("Penumbra redraw Event for " + item.ObjectKind);
//_transientResourceManager.CleanSemiTransientResources(item.ObjectKind);
item.HasUnprocessedUpdate = true;
}
}
@@ -178,7 +190,7 @@ namespace MareSynchronos.Managers
private void OnPlayerOrAttachedObjectsChanged()
{
var unprocessedObjects = playerRelatedObjects.Where(c => c.HasUnprocessedUpdate).ToList();
var unprocessedObjects = playerRelatedObjects.Where(c => c.HasUnprocessedUpdate || c.HasTransientsUpdate).ToList();
foreach (var unprocessedObject in unprocessedObjects)
{
unprocessedObject.IsProcessing = true;

View File

@@ -2,8 +2,11 @@
using MareSynchronos.Models;
using MareSynchronos.Utils;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace MareSynchronos.Managers
{
@@ -16,8 +19,9 @@ namespace MareSynchronos.Managers
public event TransientResourceLoadedEvent? TransientResourceLoaded;
private Dictionary<IntPtr, HashSet<string>> TransientResources { get; } = new();
private Dictionary<ObjectKind, HashSet<FileReplacement>> SemiTransientResources { get; } = new();
private ConcurrentDictionary<IntPtr, HashSet<string>> TransientResources { get; } = new();
private ConcurrentDictionary<ObjectKind, HashSet<FileReplacement>> SemiTransientResources { get; } = new();
private CancellationTokenSource transientInvokeDelayCts = new CancellationTokenSource();
public TransientResourceManager(IpcManager manager, DalamudUtil dalamudUtil)
{
manager.PenumbraResourceLoadEvent += Manager_PenumbraResourceLoadEvent;
@@ -42,7 +46,7 @@ namespace MareSynchronos.Managers
if (!dalamudUtil.IsGameObjectPresent(item.Key))
{
Logger.Debug("Object not present anymore: " + item.Key.ToString("X"));
TransientResources.Remove(item.Key);
TransientResources.TryRemove(item.Key, out _);
}
}
}
@@ -138,13 +142,23 @@ namespace MareSynchronos.Managers
SemiTransientResources[objectKind].RemoveWhere(f => f.GamePaths.First().ToLowerInvariant() == item.ToLowerInvariant());
}
if (!SemiTransientResources[objectKind].Any(f => f.GamePaths.First().ToLowerInvariant() == item.ToLowerInvariant()))
try
{
Logger.Debug("Persisting " + item.ToLowerInvariant());
var fileReplacement = createFileReplacement(item.ToLowerInvariant(), true);
if (!fileReplacement.HasFileReplacement)
fileReplacement = createFileReplacement(item.ToLowerInvariant(), false);
SemiTransientResources[objectKind].Add(fileReplacement);
if (!SemiTransientResources[objectKind].Any(f => f.GamePaths.First().ToLowerInvariant() == item.ToLowerInvariant()))
{
Logger.Debug("Persisting " + item.ToLowerInvariant());
var fileReplacement = createFileReplacement(item.ToLowerInvariant(), true);
if (!fileReplacement.HasFileReplacement)
fileReplacement = createFileReplacement(item.ToLowerInvariant(), false);
SemiTransientResources[objectKind].Add(fileReplacement);
}
}
catch (Exception ex)
{
Logger.Warn("Issue during transient file persistence");
Logger.Warn(ex.Message);
Logger.Warn(ex.StackTrace.ToString());
}
}