various fixes and improvements for drawing checks and data sending

This commit is contained in:
rootdarkarchon
2023-05-03 21:59:44 +02:00
parent ae5f1e9527
commit 3448601b6f
10 changed files with 242 additions and 147 deletions

View File

@@ -375,7 +375,7 @@ public class PlayerDataFactory
// gather up data from ipc
previousData.ManipulationString = _ipcManager.PenumbraGetMetaManipulations();
previousData.HeelsOffset = _ipcManager.GetHeelsOffset();
Task<float> getHeelsOffset = _ipcManager.GetHeelsOffsetAsync();
Task<string> getGlamourerData = _ipcManager.GlamourerGetCharacterCustomizationAsync(playerRelatedObject.Address);
Task<string> getCustomizeData = _ipcManager.GetCustomizePlusScaleAsync();
Task<string> getPalettePlusData = _ipcManager.PalettePlusBuildPaletteAsync();
@@ -387,6 +387,8 @@ public class PlayerDataFactory
_logger.LogDebug("Palette is now: {data}", previousData.PalettePlusPalette);
previousData.HonorificData = _ipcManager.HonorificGetTitle();
_logger.LogDebug("Honorific is now: {data}", previousData.HonorificData);
previousData.HeelsOffset = await getHeelsOffset.ConfigureAwait(false);
_logger.LogDebug("Heels is now: {heels}", previousData.HeelsOffset);
st.Stop();
_logger.LogInformation("Building character data for {obj} took {time}ms", objectKind, TimeSpan.FromTicks(st.ElapsedTicks).TotalMilliseconds);

View File

@@ -1,6 +1,4 @@
using FFXIVClientStructs.FFXIV.Client.Game.Character;
using FFXIVClientStructs.FFXIV.Client.Game.Object;
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
using MareSynchronos.Services;
using MareSynchronos.Services.Mediator;
using Microsoft.Extensions.Logging;
@@ -61,6 +59,7 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase
Mediator.Subscribe<CutsceneEndMessage>(this, (_) =>
{
_haltProcessing = false;
ZoneSwitchEnd();
});
Mediator.Subscribe<PenumbraStartRedrawMessage>(this, (msg) =>
{
@@ -93,12 +92,16 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase
private IntPtr DrawObjectAddress { get; set; }
private byte[] EquipSlotData { get; set; } = new byte[40];
public async Task ActOnFrameworkAfterEnsureNoDrawAsync(Action act, CancellationToken token)
public async Task ActOnFrameworkAfterEnsureNoDrawAsync(Action<Dalamud.Game.ClientState.Objects.Types.Character> act, CancellationToken token)
{
while (await _dalamudUtil.RunOnFrameworkThread(() =>
{
if (IsBeingDrawn()) return true;
act();
var gameObj = _dalamudUtil.CreateGameObject(Address);
if (gameObj is Dalamud.Game.ClientState.Objects.Types.Character chara)
{
act.Invoke(chara);
}
return false;
}).ConfigureAwait(false))
{
@@ -117,6 +120,12 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase
return _dalamudUtil.CreateGameObject(Address);
}
public void Invalidate()
{
Address = IntPtr.Zero;
DrawObjectAddress = IntPtr.Zero;
}
public async Task<bool> IsBeingDrawnRunOnFrameworkAsync()
{
return await _dalamudUtil.RunOnFrameworkThread(IsBeingDrawn).ConfigureAwait(false);
@@ -146,7 +155,7 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase
Address = _getAddress();
if (Address != IntPtr.Zero)
{
var drawObjAddr = (IntPtr)((GameObject*)Address)->DrawObject;
var drawObjAddr = (IntPtr)((FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject*)Address)->DrawObject;
DrawObjectAddress = drawObjAddr;
}
else
@@ -165,7 +174,7 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase
_clearCts?.Cancel();
_clearCts = null;
}
var chara = (Character*)Address;
var chara = (FFXIVClientStructs.FFXIV.Client.Game.Character.Character*)Address;
var name = new ByteString(chara->GameObject.Name).ToString();
bool nameChange = !string.Equals(name, Name, StringComparison.Ordinal);
Name = name;
@@ -259,11 +268,17 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase
private unsafe IntPtr GetDrawObj(nint curPtr)
{
Logger.LogTrace("[{this}] IsBeingDrawnRunOnFramework, Getting new DrawObject", this);
return (IntPtr)((GameObject*)curPtr)->DrawObject;
return (IntPtr)((FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject*)curPtr)->DrawObject;
}
private bool IsBeingDrawn()
{
if (_dalamudUtil.IsAnythingDrawing)
{
Logger.LogTrace("[{this}] IsBeingDrawnRunOnFramework, Global draw block", this);
return true;
}
var curPtr = _getAddress();
Logger.LogTrace("[{this}] IsBeingDrawnRunOnFramework, CurPtr: {ptr}", this, curPtr.ToString("X"));
@@ -289,7 +304,7 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase
var drawObjZero = drawObj == IntPtr.Zero;
Logger.LogTrace("[{this}] IsBeingDrawnRunOnFramework, Condition IsDrawObjZero: {cond}", this, drawObjZero);
if (drawObjZero) return true;
var renderFlags = (((GameObject*)curPtr)->RenderFlags) != 0x0;
var renderFlags = (((FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject*)curPtr)->RenderFlags) != 0x0;
Logger.LogTrace("[{this}] IsBeingDrawnRunOnFramework, Condition RenderFlags: {cond}", this, renderFlags);
if (renderFlags) return true;
var modelInSlotLoaded = (((CharacterBase*)drawObj)->HasModelInSlotLoaded != 0);
@@ -303,7 +318,7 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase
}
return drawObj == IntPtr.Zero
|| ((GameObject*)curPtr)->RenderFlags != 0x0;
|| ((FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject*)curPtr)->RenderFlags != 0x0;
}
private void ZoneSwitchEnd()

View File

@@ -14,10 +14,8 @@ using MareSynchronos.Utils;
using MareSynchronos.WebAPI.Files;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using static System.Net.Mime.MediaTypeNames;
using ObjectKind = MareSynchronos.API.Data.Enum.ObjectKind;
namespace MareSynchronos.PlayerData.Pairs;
@@ -55,6 +53,12 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
_lifetime = lifetime;
_fileDbManager = fileDbManager;
Mediator.Subscribe<FrameworkUpdateMessage>(this, (_) => FrameworkUpdate());
Mediator.Subscribe<ZoneSwitchStartMessage>(this, (_) =>
{
_charaHandler?.Invalidate();
IsVisible = false;
}
);
_pluginWarnings ??= new()
{
ShownCustomizePlusWarning = mareConfigService.Current.DisableOptionalPluginWarnings,
@@ -445,16 +449,14 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
if (updateModdedPaths && (moddedPaths.Any() || !string.IsNullOrEmpty(charaData.ManipulationData)))
{
await _charaHandler!.ActOnFrameworkAfterEnsureNoDrawAsync(() => _ipcManager
await _charaHandler!.ActOnFrameworkAfterEnsureNoDrawAsync((_) => _ipcManager
.PenumbraRemoveTemporaryCollectionAsync(Logger, _applicationId, PlayerName!)
.ConfigureAwait(true).GetAwaiter().GetResult(), token).ConfigureAwait(false);
token.ThrowIfCancellationRequested();
await _charaHandler!.ActOnFrameworkAfterEnsureNoDrawAsync(() =>
await _charaHandler!.ActOnFrameworkAfterEnsureNoDrawAsync((chara) =>
{
var gameObj = _charaHandler!.GetGameObject();
if (gameObj == null) return;
var objTableIndex = gameObj.ObjectTableIndex();
var objTableIndex = chara.ObjectTableIndex();
_ipcManager.PenumbraSetTemporaryModsAsync(Logger, _applicationId, PlayerName!, objTableIndex, moddedPaths, charaData.ManipulationData)
.ConfigureAwait(true).GetAwaiter().GetResult();
}, token).ConfigureAwait(false);
@@ -510,6 +512,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
_framesSinceNotVisible++;
if (_framesSinceNotVisible > 30)
{
_framesSinceNotVisible = 30;
IsVisible = false;
Logger.LogTrace("{this} visibility changed, now: {visi}", this, IsVisible);
}
@@ -627,7 +630,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
if (minionOrMount != IntPtr.Zero)
{
using GameObjectHandler tempHandler = await _gameObjectHandlerFactory.Create(ObjectKind.MinionOrMount, () => minionOrMount, false).ConfigureAwait(false);
await _ipcManager.PenumbraRedrawAsync(Logger, tempHandler, applicationId, cancelToken.Token, fireAndForget: false).ConfigureAwait(false);
await _ipcManager.PenumbraRedrawAsync(Logger, tempHandler, applicationId, cancelToken.Token).ConfigureAwait(false);
}
}
else if (objectKind == ObjectKind.Pet)
@@ -636,7 +639,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
if (pet != IntPtr.Zero)
{
using GameObjectHandler tempHandler = await _gameObjectHandlerFactory.Create(ObjectKind.Pet, () => pet, false).ConfigureAwait(false);
await _ipcManager.PenumbraRedrawAsync(Logger, tempHandler, applicationId, cancelToken.Token, fireAndForget: false).ConfigureAwait(false);
await _ipcManager.PenumbraRedrawAsync(Logger, tempHandler, applicationId, cancelToken.Token).ConfigureAwait(false);
}
}
else if (objectKind == ObjectKind.Companion)
@@ -645,7 +648,7 @@ public sealed class CachedPlayer : DisposableMediatorSubscriberBase
if (companion != IntPtr.Zero)
{
using GameObjectHandler tempHandler = await _gameObjectHandlerFactory.Create(ObjectKind.Pet, () => companion, false).ConfigureAwait(false);
await _ipcManager.PenumbraRedrawAsync(Logger, tempHandler, applicationId, cancelToken.Token, fireAndForget: false).ConfigureAwait(false);
await _ipcManager.PenumbraRedrawAsync(Logger, tempHandler, applicationId, cancelToken.Token).ConfigureAwait(false);
}
}
}

View File

@@ -41,6 +41,7 @@ public class OnlinePlayerManager : DisposableMediatorSubscriberBase
}
});
Mediator.Subscribe<CachedPlayerVisibleMessage>(this, (msg) => _newVisiblePlayers.Add(msg.Player));
Mediator.Subscribe<ConnectedMessage>(this, (_) => PushCharacterData(_pairManager.GetVisibleUsers()));
}
private void FrameworkOnUpdate()

View File

@@ -18,6 +18,7 @@ public sealed class CacheCreationService : DisposableMediatorSubscriberBase
private readonly Dictionary<ObjectKind, GameObjectHandler> _playerRelatedObjects = new();
private Task? _cacheCreationTask;
private CancellationTokenSource _honorificCts = new();
private bool _isZoning = false;
private CancellationTokenSource _palettePlusCts = new();
public CacheCreationService(ILogger<CacheCreationService> logger, MareMediator mediator, GameObjectHandlerFactory gameObjectHandlerFactory,
@@ -27,7 +28,7 @@ public sealed class CacheCreationService : DisposableMediatorSubscriberBase
Mediator.Subscribe<CreateCacheForObjectMessage>(this, (msg) =>
{
Logger.LogDebug("Received CreateCacheForObject for {handler}, updating player", msg.ObjectToCreateFor);
Logger.LogDebug("Received CreateCacheForObject for {handler}, updating", msg.ObjectToCreateFor);
_cacheCreateLock.Wait();
_cachesToCreate[msg.ObjectToCreateFor.ObjectKind] = msg.ObjectToCreateFor;
_cacheCreateLock.Release();
@@ -37,25 +38,32 @@ public sealed class CacheCreationService : DisposableMediatorSubscriberBase
{
Task.Run(() =>
{
Logger.LogTrace("Clearing cache for {obj}", msg.ObjectToCreateFor);
_playerData.FileReplacements.Remove(msg.ObjectToCreateFor.ObjectKind);
_playerData.GlamourerString.Remove(msg.ObjectToCreateFor.ObjectKind);
Mediator.Publish(new CharacterDataCreatedMessage(_playerData.ToAPI()));
});
});
Mediator.Subscribe<ZoneSwitchStartMessage>(this, (msg) => _isZoning = true);
Mediator.Subscribe<ZoneSwitchEndMessage>(this, (msg) => _isZoning = false);
Mediator.Subscribe<DelayedFrameworkUpdateMessage>(this, (msg) => ProcessCacheCreation());
Mediator.Subscribe<CustomizePlusMessage>(this, async (_) =>
{
if (_isZoning) return;
Logger.LogDebug("Received CustomizePlus change, updating player");
await AddPlayerCacheToCreate().ConfigureAwait(false);
});
Mediator.Subscribe<HeelsOffsetMessage>(this, async (_) =>
{
if (_isZoning) return;
Logger.LogDebug("Received Heels Offset change, updating player");
await AddPlayerCacheToCreate().ConfigureAwait(false);
});
Mediator.Subscribe<PalettePlusMessage>(this, (msg) =>
{
if (_isZoning) return;
if (msg.Character.Address == _playerRelatedObjects[ObjectKind.Player].Address)
{
Logger.LogDebug("Received PalettePlus change, updating player");
@@ -64,6 +72,7 @@ public sealed class CacheCreationService : DisposableMediatorSubscriberBase
});
Mediator.Subscribe<HonorificMessage>(this, (msg) =>
{
if (_isZoning) return;
if (!string.Equals(msg.NewHonorificTitle, _playerData.HonorificData, StringComparison.Ordinal))
{
Logger.LogDebug("Received Honorific change, updating player");
@@ -76,7 +85,7 @@ public sealed class CacheCreationService : DisposableMediatorSubscriberBase
await AddPlayerCacheToCreate().ConfigureAwait(false);
});
_playerRelatedObjects[ObjectKind.Player] = gameObjectHandlerFactory.Create(ObjectKind.Player, () => dalamudUtil.GetPlayerPointer(), true)
_playerRelatedObjects[ObjectKind.Player] = gameObjectHandlerFactory.Create(ObjectKind.Player, dalamudUtil.GetPlayerPointer, true)
.GetAwaiter().GetResult();
_playerRelatedObjects[ObjectKind.MinionOrMount] = gameObjectHandlerFactory.Create(ObjectKind.MinionOrMount, () => dalamudUtil.GetMinionOrMount(), true)
.GetAwaiter().GetResult();
@@ -131,6 +140,8 @@ public sealed class CacheCreationService : DisposableMediatorSubscriberBase
private void ProcessCacheCreation()
{
if (_isZoning) return;
if (_cachesToCreate.Any() && (_cacheCreationTask?.IsCompleted ?? true))
{
_cacheCreateLock.Wait();