128 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			128 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using MareSynchronos.API.Data.Enum;
 | |
| using MareSynchronos.Interop.Ipc;
 | |
| using MareSynchronos.PlayerData.Factories;
 | |
| using MareSynchronos.PlayerData.Handlers;
 | |
| using MareSynchronos.Services.CharaData.Models;
 | |
| using MareSynchronos.Services.Mediator;
 | |
| using Microsoft.Extensions.Logging;
 | |
| 
 | |
| namespace MareSynchronos.Services;
 | |
| 
 | |
| public sealed class CharaDataCharacterHandler : DisposableMediatorSubscriberBase
 | |
| {
 | |
|     private readonly GameObjectHandlerFactory _gameObjectHandlerFactory;
 | |
|     private readonly DalamudUtilService _dalamudUtilService;
 | |
|     private readonly IpcManager _ipcManager;
 | |
|     private readonly HashSet<HandledCharaDataEntry> _handledCharaData = [];
 | |
| 
 | |
|     public IEnumerable<HandledCharaDataEntry> HandledCharaData => _handledCharaData;
 | |
| 
 | |
|     public CharaDataCharacterHandler(ILogger<CharaDataCharacterHandler> logger, MareMediator mediator,
 | |
|         GameObjectHandlerFactory gameObjectHandlerFactory, DalamudUtilService dalamudUtilService,
 | |
|         IpcManager ipcManager)
 | |
|         : base(logger, mediator)
 | |
|     {
 | |
|         _gameObjectHandlerFactory = gameObjectHandlerFactory;
 | |
|         _dalamudUtilService = dalamudUtilService;
 | |
|         _ipcManager = ipcManager;
 | |
|         mediator.Subscribe<GposeEndMessage>(this, msg =>
 | |
|         {
 | |
|             foreach (var chara in _handledCharaData)
 | |
|             {
 | |
|                 _ = RevertHandledChara(chara, reapplyPose: false);
 | |
|             }
 | |
|         });
 | |
| 
 | |
|         mediator.Subscribe<CutsceneFrameworkUpdateMessage>(this, (_) => HandleCutsceneFrameworkUpdate());
 | |
|     }
 | |
| 
 | |
|     private void HandleCutsceneFrameworkUpdate()
 | |
|     {
 | |
|         if (!_dalamudUtilService.IsInGpose) return;
 | |
| 
 | |
|         foreach (var entry in _handledCharaData.ToList())
 | |
|         {
 | |
|             var chara = _dalamudUtilService.GetGposeCharacterFromObjectTableByName(entry.Name, onlyGposeCharacters: true);
 | |
|             if (chara is null)
 | |
|             {
 | |
|                 RevertChara(entry.Name, entry.CustomizePlus).GetAwaiter().GetResult();
 | |
|                 _handledCharaData.Remove(entry);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     protected override void Dispose(bool disposing)
 | |
|     {
 | |
|         base.Dispose(disposing);
 | |
|         foreach (var chara in _handledCharaData)
 | |
|         {
 | |
|             _ = RevertHandledChara(chara, reapplyPose: false);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     public async Task RevertChara(string name, Guid? cPlusId, bool reapplyPose = true)
 | |
|     {
 | |
|         Guid applicationId = Guid.NewGuid();
 | |
|         await _ipcManager.Glamourer.RevertByNameAsync(Logger, name, applicationId).ConfigureAwait(false);
 | |
|         if (cPlusId != null)
 | |
|         {
 | |
|             await _ipcManager.CustomizePlus.RevertByIdAsync(cPlusId).ConfigureAwait(false);
 | |
|         }
 | |
|         using var handler = await _gameObjectHandlerFactory.Create(ObjectKind.Player,
 | |
|             () => _dalamudUtilService.GetGposeCharacterFromObjectTableByName(name, _dalamudUtilService.IsInGpose)?.Address ?? IntPtr.Zero, false)
 | |
|             .ConfigureAwait(false);
 | |
|         if (handler.Address != nint.Zero)
 | |
|             await _ipcManager.Penumbra.RedrawAsync(Logger, handler, applicationId, CancellationToken.None).ConfigureAwait(false);
 | |
|     }
 | |
| 
 | |
|     public async Task<bool> RevertHandledChara(string name, bool reapplyPose = true)
 | |
|     {
 | |
|         var handled = _handledCharaData.FirstOrDefault(f => string.Equals(f.Name, name, StringComparison.Ordinal));
 | |
|         if (handled == null) return false;
 | |
|         _handledCharaData.Remove(handled);
 | |
|         await _dalamudUtilService.RunOnFrameworkThread(() => RevertChara(handled.Name, handled.CustomizePlus, reapplyPose)).ConfigureAwait(false);
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     public Task RevertHandledChara(HandledCharaDataEntry? handled, bool reapplyPose = true)
 | |
|     {
 | |
|         if (handled == null) return Task.CompletedTask;
 | |
|         _handledCharaData.Remove(handled);
 | |
|         return _dalamudUtilService.RunOnFrameworkThread(() => RevertChara(handled.Name, handled.CustomizePlus, reapplyPose));
 | |
|     }
 | |
| 
 | |
|     internal void AddHandledChara(HandledCharaDataEntry handledCharaDataEntry)
 | |
|     {
 | |
|         _handledCharaData.Add(handledCharaDataEntry);
 | |
|     }
 | |
| 
 | |
|     public void UpdateHandledData(Dictionary<string, CharaDataMetaInfoExtendedDto?> newData)
 | |
|     {
 | |
|         foreach (var handledData in _handledCharaData)
 | |
|         {
 | |
|             if (newData.TryGetValue(handledData.MetaInfo.FullId, out var metaInfo) && metaInfo != null)
 | |
|             {
 | |
|                 handledData.MetaInfo = metaInfo;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     public async Task<GameObjectHandler?> TryCreateGameObjectHandler(string name, bool gPoseOnly = false)
 | |
|     {
 | |
|         var handler = await _gameObjectHandlerFactory.Create(ObjectKind.Player,
 | |
|             () => _dalamudUtilService.GetGposeCharacterFromObjectTableByName(name, gPoseOnly && _dalamudUtilService.IsInGpose)?.Address ?? IntPtr.Zero, false)
 | |
|             .ConfigureAwait(false);
 | |
|         if (handler.Address == nint.Zero) return null;
 | |
|         return handler;
 | |
|     }
 | |
| 
 | |
|     public async Task<GameObjectHandler?> TryCreateGameObjectHandler(int index)
 | |
|     {
 | |
|         var handler = await _gameObjectHandlerFactory.Create(ObjectKind.Player,
 | |
|             () => _dalamudUtilService.GetCharacterFromObjectTableByIndex(index)?.Address ?? IntPtr.Zero, false)
 | |
|             .ConfigureAwait(false);
 | |
|         if (handler.Address == nint.Zero) return null;
 | |
|         return handler;
 | |
|     }
 | |
| }
 | 
