merge from main

This commit is contained in:
Stanley Dimant
2022-09-03 15:06:01 +02:00
11 changed files with 183 additions and 130 deletions

View File

@@ -33,14 +33,26 @@ public class CharacterDataFactory
this.transientResourceManager = transientResourceManager; this.transientResourceManager = transientResourceManager;
} }
public CharacterData BuildCharacterData(CharacterData previousData, ObjectKind objectKind, IntPtr playerPointer, CancellationToken token) public unsafe CharacterData BuildCharacterData(CharacterData previousData, ObjectKind objectKind, IntPtr playerPointer, CancellationToken token)
{ {
if (!_ipcManager.Initialized) if (!_ipcManager.Initialized)
{ {
throw new ArgumentException("Penumbra is not connected"); throw new ArgumentException("Penumbra is not connected");
} }
if (playerPointer == IntPtr.Zero) bool pointerIsZero = true;
try
{
pointerIsZero = playerPointer == IntPtr.Zero || ((Character*)playerPointer)->GameObject.GetDrawObject() == null;
}
catch (Exception ex)
{
Logger.Warn("Could not create data for " + objectKind);
Logger.Warn(ex.Message);
Logger.Warn(ex.StackTrace ?? string.Empty);
}
if (pointerIsZero)
{ {
Logger.Verbose("Pointer was zero for " + objectKind); Logger.Verbose("Pointer was zero for " + objectKind);
previousData.FileReplacements.Remove(objectKind); previousData.FileReplacements.Remove(objectKind);
@@ -191,7 +203,7 @@ public class CharacterDataFactory
private void AddReplacementsFromTexture(string texPath, ObjectKind objectKind, CharacterData cache, int inheritanceLevel = 0, bool doNotReverseResolve = true) private void AddReplacementsFromTexture(string texPath, ObjectKind objectKind, CharacterData cache, int inheritanceLevel = 0, bool doNotReverseResolve = true)
{ {
if (texPath.IsNullOrEmpty()) return; if (string.IsNullOrEmpty(texPath)) return;
//Logger.Verbose("Adding File Replacement for Texture " + texPath); //Logger.Verbose("Adding File Replacement for Texture " + texPath);
@@ -220,6 +232,11 @@ public class CharacterDataFactory
private unsafe CharacterData CreateCharacterData(CharacterData previousData, ObjectKind objectKind, IntPtr charaPointer, CancellationToken token) private unsafe CharacterData CreateCharacterData(CharacterData previousData, ObjectKind objectKind, IntPtr charaPointer, CancellationToken token)
{ {
if (previousData.FileReplacements.ContainsKey(objectKind))
{
previousData.FileReplacements[objectKind].Clear();
}
Stopwatch st = Stopwatch.StartNew(); Stopwatch st = Stopwatch.StartNew();
var chara = _dalamudUtil.CreateGameObject(charaPointer)!; var chara = _dalamudUtil.CreateGameObject(charaPointer)!;
while (!_dalamudUtil.IsObjectPresent(chara)) while (!_dalamudUtil.IsObjectPresent(chara))
@@ -229,17 +246,9 @@ public class CharacterDataFactory
} }
_dalamudUtil.WaitWhileCharacterIsDrawing(charaPointer); _dalamudUtil.WaitWhileCharacterIsDrawing(charaPointer);
if (previousData.FileReplacements.ContainsKey(objectKind))
{
previousData.FileReplacements[objectKind].Clear();
}
previousData.ManipulationString = _ipcManager.PenumbraGetMetaManipulations(); previousData.ManipulationString = _ipcManager.PenumbraGetMetaManipulations();
if (objectKind is not ObjectKind.Mount) previousData.GlamourerString[objectKind] = _ipcManager.GlamourerGetCharacterCustomization(chara);
{
previousData.GlamourerString[objectKind] = _ipcManager.GlamourerGetCharacterCustomization(chara);
}
var human = (Human*)((Character*)charaPointer)->GameObject.GetDrawObject(); var human = (Human*)((Character*)charaPointer)->GameObject.GetDrawObject();
for (var mdlIdx = 0; mdlIdx < human->CharacterBase.SlotCount; ++mdlIdx) for (var mdlIdx = 0; mdlIdx < human->CharacterBase.SlotCount; ++mdlIdx)

View File

@@ -9,9 +9,9 @@ using FFXIVClientStructs.FFXIV.Client.Game.Character;
using MareSynchronos.API; using MareSynchronos.API;
using MareSynchronos.FileCacheDB; using MareSynchronos.FileCacheDB;
using MareSynchronos.Interop; using MareSynchronos.Interop;
using MareSynchronos.Models;
using MareSynchronos.Utils; using MareSynchronos.Utils;
using MareSynchronos.WebAPI; using MareSynchronos.WebAPI;
using Penumbra.GameData.Structs;
namespace MareSynchronos.Managers; namespace MareSynchronos.Managers;
@@ -59,7 +59,7 @@ public class CachedPlayer
private CharacterCacheDto _cachedData = new(); private CharacterCacheDto _cachedData = new();
private CharacterEquipment? _currentCharacterEquipment; private PlayerRelatedObject? _currentCharacterEquipment;
public void ApplyCharacterData(CharacterCacheDto characterData) public void ApplyCharacterData(CharacterCacheDto characterData)
{ {
@@ -235,15 +235,29 @@ public class CachedPlayer
RequestedPenumbraRedraw = true; RequestedPenumbraRedraw = true;
Logger.Debug( Logger.Debug(
$"Request Redraw for {PlayerName}"); $"Request Redraw for {PlayerName}");
_ipcManager.GlamourerApplyAll(glamourerData, PlayerCharacter.Address); if (_ipcManager.CheckGlamourerApi() && !string.IsNullOrEmpty(glamourerData))
}
else if (objectKind == ObjectKind.Minion)
{
var minion = ((Character*)PlayerCharacter.Address)->CompanionObject;
if (minion != null)
{ {
Logger.Debug($"Request Redraw for Minion"); _ipcManager.GlamourerApplyAll(glamourerData, PlayerCharacter.Address);
_ipcManager.GlamourerApplyAll(glamourerData, obj: (IntPtr)minion); }
else
{
_ipcManager.PenumbraRedraw(PlayerCharacter.Address);
}
}
else if (objectKind == ObjectKind.MinionOrMount)
{
var minionOrMount = ((Character*)PlayerCharacter.Address)->CompanionObject;
if (minionOrMount != null)
{
Logger.Debug($"Request Redraw for Minion/Mount");
if (_ipcManager.CheckGlamourerApi() && !string.IsNullOrEmpty(glamourerData))
{
_ipcManager.GlamourerApplyAll(glamourerData, obj: (IntPtr)minionOrMount);
}
else
{
_ipcManager.PenumbraRedraw((IntPtr)minionOrMount);
}
} }
} }
else if (objectKind == ObjectKind.Pet) else if (objectKind == ObjectKind.Pet)
@@ -252,7 +266,14 @@ public class CachedPlayer
if (pet != IntPtr.Zero) if (pet != IntPtr.Zero)
{ {
Logger.Debug("Request Redraw for Pet"); Logger.Debug("Request Redraw for Pet");
_ipcManager.GlamourerApplyAll(glamourerData, pet); if (_ipcManager.CheckGlamourerApi() && !string.IsNullOrEmpty(glamourerData))
{
_ipcManager.GlamourerApplyAll(glamourerData, pet);
}
else
{
_ipcManager.PenumbraRedraw(pet);
}
} }
} }
else if (objectKind == ObjectKind.Companion) else if (objectKind == ObjectKind.Companion)
@@ -261,16 +282,14 @@ public class CachedPlayer
if (companion != IntPtr.Zero) if (companion != IntPtr.Zero)
{ {
Logger.Debug("Request Redraw for Companion"); Logger.Debug("Request Redraw for Companion");
_ipcManager.GlamourerApplyAll(glamourerData, companion); if (_ipcManager.CheckGlamourerApi() && !string.IsNullOrEmpty(glamourerData))
} {
} _ipcManager.GlamourerApplyAll(glamourerData, companion);
else if (objectKind == ObjectKind.Mount) }
{ else
var mount = ((CharaExt*)PlayerCharacter.Address)->Mount; {
if (mount != null) _ipcManager.PenumbraRedraw(companion);
{ }
Logger.Debug($"Request Redraw for Mount");
_ipcManager.PenumbraRedraw((IntPtr)mount);
} }
} }
} }
@@ -281,15 +300,22 @@ public class CachedPlayer
if (objectKind == ObjectKind.Player) if (objectKind == ObjectKind.Player)
{ {
_ipcManager.GlamourerApplyOnlyCustomization(_originalGlamourerData, PlayerCharacter); if (_ipcManager.CheckGlamourerApi())
_ipcManager.GlamourerApplyOnlyEquipment(_lastGlamourerData, PlayerCharacter);
}
else if (objectKind == ObjectKind.Minion)
{
var minion = ((Character*)PlayerCharacter.Address)->CompanionObject;
if (minion != null)
{ {
_ipcManager.PenumbraRedraw((IntPtr)minion); _ipcManager.GlamourerApplyOnlyCustomization(_originalGlamourerData, PlayerCharacter);
_ipcManager.GlamourerApplyOnlyEquipment(_lastGlamourerData, PlayerCharacter);
}
else
{
_ipcManager.PenumbraRedraw(PlayerCharacter.Address);
}
}
else if (objectKind == ObjectKind.MinionOrMount)
{
var minionOrMount = ((Character*)PlayerCharacter.Address)->CompanionObject;
if (minionOrMount != null)
{
_ipcManager.PenumbraRedraw((IntPtr)minionOrMount);
} }
} }
else if (objectKind == ObjectKind.Pet) else if (objectKind == ObjectKind.Pet)
@@ -308,14 +334,6 @@ public class CachedPlayer
_ipcManager.PenumbraRedraw(companion); _ipcManager.PenumbraRedraw(companion);
} }
} }
else if (objectKind == ObjectKind.Mount)
{
var mount = ((CharaExt*)PlayerCharacter.Address)->Mount;
if (mount != null)
{
_ipcManager.PenumbraRedraw((IntPtr)mount);
}
}
} }
public void DisposePlayer() public void DisposePlayer()
@@ -363,7 +381,8 @@ public class CachedPlayer
_dalamudUtil.FrameworkUpdate += DalamudUtilOnFrameworkUpdate; _dalamudUtil.FrameworkUpdate += DalamudUtilOnFrameworkUpdate;
_ipcManager.PenumbraRedrawEvent += IpcManagerOnPenumbraRedrawEvent; _ipcManager.PenumbraRedrawEvent += IpcManagerOnPenumbraRedrawEvent;
_originalGlamourerData = _ipcManager.GlamourerGetCharacterCustomization(PlayerCharacter); _originalGlamourerData = _ipcManager.GlamourerGetCharacterCustomization(PlayerCharacter);
_currentCharacterEquipment = new CharacterEquipment(PlayerCharacter); _currentCharacterEquipment = new PlayerRelatedObject(ObjectKind.Player, IntPtr.Zero, IntPtr.Zero,
() => _dalamudUtil.GetPlayerCharacterFromObjectTableByName(PlayerName)?.Address ?? IntPtr.Zero);
_isDisposed = false; _isDisposed = false;
if (cache != null) if (cache != null)
{ {
@@ -382,7 +401,8 @@ public class CachedPlayer
return; return;
} }
if (!_currentCharacterEquipment!.CompareAndUpdate(PlayerCharacter)) _currentCharacterEquipment?.CheckAndUpdateObject();
if (_currentCharacterEquipment?.HasUnprocessedUpdate ?? false)
{ {
OnPlayerChanged(); OnPlayerChanged();
} }
@@ -406,7 +426,9 @@ public class CachedPlayer
_penumbraRedrawEventTask = Task.Run(() => _penumbraRedrawEventTask = Task.Run(() =>
{ {
PlayerCharacter = player; PlayerCharacter = player;
_dalamudUtil.WaitWhileCharacterIsDrawing(PlayerCharacter.Address); using var cts = new CancellationTokenSource();
cts.CancelAfter(TimeSpan.FromSeconds(5));
_dalamudUtil.WaitWhileCharacterIsDrawing(PlayerCharacter.Address, cts.Token);
if (RequestedPenumbraRedraw == false) if (RequestedPenumbraRedraw == false)
{ {
@@ -425,6 +447,7 @@ public class CachedPlayer
private void OnPlayerChanged() private void OnPlayerChanged()
{ {
Logger.Debug($"Player {PlayerName} changed, PenumbraRedraw is {RequestedPenumbraRedraw}"); Logger.Debug($"Player {PlayerName} changed, PenumbraRedraw is {RequestedPenumbraRedraw}");
_currentCharacterEquipment!.HasUnprocessedUpdate = false;
if (!RequestedPenumbraRedraw && PlayerCharacter is not null) if (!RequestedPenumbraRedraw && PlayerCharacter is not null)
{ {
Logger.Debug($"Saving new Glamourer data"); Logger.Debug($"Saving new Glamourer data");

View File

@@ -158,12 +158,19 @@ namespace MareSynchronos.Managers
public string GlamourerGetCharacterCustomization(GameObject character) public string GlamourerGetCharacterCustomization(GameObject character)
{ {
if (!CheckGlamourerApi()) return string.Empty; if (!CheckGlamourerApi()) return string.Empty;
var glamourerString = _glamourerGetAllCustomization!.InvokeFunc(character); try
byte[] bytes = Convert.FromBase64String(glamourerString); {
// ignore transparency var glamourerString = _glamourerGetAllCustomization!.InvokeFunc(character);
bytes[88] = 128; byte[] bytes = Convert.FromBase64String(glamourerString);
bytes[89] = 63; // ignore transparency
return Convert.ToBase64String(bytes); bytes[88] = 128;
bytes[89] = 63;
return Convert.ToBase64String(bytes);
}
catch
{
return string.Empty;
}
} }
public void GlamourerRevertCharacterCustomization(GameObject character) public void GlamourerRevertCharacterCustomization(GameObject character)

View File

@@ -5,12 +5,10 @@ using System;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using MareSynchronos.API; using MareSynchronos.API;
using Penumbra.GameData.Structs;
using FFXIVClientStructs.FFXIV.Client.Game.Character; using FFXIVClientStructs.FFXIV.Client.Game.Character;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using MareSynchronos.Models; using MareSynchronos.Models;
using MareSynchronos.Interop;
namespace MareSynchronos.Managers namespace MareSynchronos.Managers
{ {
@@ -30,7 +28,6 @@ namespace MareSynchronos.Managers
private CancellationTokenSource? _playerChangedCts = new(); private CancellationTokenSource? _playerChangedCts = new();
private DateTime _lastPlayerObjectCheck; private DateTime _lastPlayerObjectCheck;
private CharacterEquipment? _currentCharacterEquipment = new();
private List<PlayerRelatedObject> playerRelatedObjects = new List<PlayerRelatedObject>(); private List<PlayerRelatedObject> playerRelatedObjects = new List<PlayerRelatedObject>();
@@ -58,10 +55,9 @@ namespace MareSynchronos.Managers
playerRelatedObjects = new List<PlayerRelatedObject>() playerRelatedObjects = new List<PlayerRelatedObject>()
{ {
new PlayerRelatedObject(ObjectKind.Player, IntPtr.Zero, IntPtr.Zero, () => _dalamudUtil.PlayerPointer), new PlayerRelatedObject(ObjectKind.Player, IntPtr.Zero, IntPtr.Zero, () => _dalamudUtil.PlayerPointer),
new PlayerRelatedObject(ObjectKind.Minion, IntPtr.Zero, IntPtr.Zero, () => (IntPtr)((Character*)_dalamudUtil.PlayerPointer)->CompanionObject), new PlayerRelatedObject(ObjectKind.MinionOrMount, IntPtr.Zero, IntPtr.Zero, () => (IntPtr)((Character*)_dalamudUtil.PlayerPointer)->CompanionObject),
new PlayerRelatedObject(ObjectKind.Pet, IntPtr.Zero, IntPtr.Zero, () => _dalamudUtil.GetPet()), new PlayerRelatedObject(ObjectKind.Pet, IntPtr.Zero, IntPtr.Zero, () => _dalamudUtil.GetPet()),
new PlayerRelatedObject(ObjectKind.Companion, IntPtr.Zero, IntPtr.Zero, () => _dalamudUtil.GetCompanion()), new PlayerRelatedObject(ObjectKind.Companion, IntPtr.Zero, IntPtr.Zero, () => _dalamudUtil.GetCompanion()),
new PlayerRelatedObject(ObjectKind.Mount, IntPtr.Zero, IntPtr.Zero, () => (IntPtr)((CharaExt*)_dalamudUtil.PlayerPointer)->Mount),
}; };
} }

View File

@@ -3,7 +3,7 @@
<PropertyGroup> <PropertyGroup>
<Authors></Authors> <Authors></Authors>
<Company></Company> <Company></Company>
<Version>0.3.4</Version> <Version>0.3.10</Version>
<Description></Description> <Description></Description>
<Copyright></Copyright> <Copyright></Copyright>
<PackageProjectUrl>https://github.com/Penumbra-Sync/client</PackageProjectUrl> <PackageProjectUrl>https://github.com/Penumbra-Sync/client</PackageProjectUrl>
@@ -21,12 +21,12 @@
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<DalamudLibPath>$(appdata)\XIVLauncher\addon\Hooks\dev\</DalamudLibPath> <DalamudLibPath>$(appdata)\XIVLauncher\addon\Hooks\Dev\</DalamudLibPath>
<AssemblyVersion></AssemblyVersion> <AssemblyVersion></AssemblyVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="DalamudPackager" Version="2.1.7" /> <PackageReference Include="DalamudPackager" Version="2.1.8" />
<PackageReference Include="lz4net" Version="1.0.15.93" /> <PackageReference Include="lz4net" Version="1.0.15.93" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="6.0.8" /> <PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="6.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.8" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.8" />
@@ -84,7 +84,7 @@
</ItemGroup> </ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent"> <Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\alpine-x64&#xD;&#xA;rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\linux-arm&#xD;&#xA;rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\linux-arm64&#xD;&#xA;rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\linux-armel&#xD;&#xA;rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\linux-mips64&#xD;&#xA;rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\linux-musl-x64&#xD;&#xA;rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\linux-x64&#xD;&#xA;rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\linux-x86&#xD;&#xA;rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\osx-x64&#xD;&#xA;rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\win-arm&#xD;&#xA;rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\win-arm64&#xD;&#xA;if $(ConfigurationName) == Debug (&#xD;&#xA;del /Q $(ProjectDir)$(OutDir)Mare.7z&#xD;&#xA;&quot;C:\Program Files\7-zip\7z.exe&quot; a $(ProjectDir)$(OutDir)Mare.7z $(ProjectDir)$(OutDir)*&#xD;&#xA;)" /> <Exec Command="rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\alpine-x64&#xD;&#xA;rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\linux-arm&#xD;&#xA;rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\linux-arm64&#xD;&#xA;rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\linux-armel&#xD;&#xA;rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\linux-mips64&#xD;&#xA;rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\linux-musl-x64&#xD;&#xA;rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\linux-x64&#xD;&#xA;rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\linux-x86&#xD;&#xA;rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\linux-s390x&#xD;&#xA;rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\osx-x64&#xD;&#xA;rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\osx-arm64&#xD;&#xA;rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\win-arm&#xD;&#xA;rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\win-arm64&#xD;&#xA;if $(ConfigurationName) == Debug (&#xD;&#xA;del /Q $(ProjectDir)$(OutDir)Mare.7z&#xD;&#xA;&quot;C:\Program Files\7-zip\7z.exe&quot; a $(ProjectDir)$(OutDir)Mare.7z $(ProjectDir)$(OutDir)*&#xD;&#xA;)" />
</Target> </Target>
</Project> </Project>

View File

@@ -47,7 +47,7 @@ namespace MareSynchronos.Models
var chara = (Character*)curPtr; var chara = (Character*)curPtr;
bool addr = Address == IntPtr.Zero || Address != curPtr; bool addr = Address == IntPtr.Zero || Address != curPtr;
bool equip = CompareAndUpdateByteData(chara->EquipSlotData, chara->CustomizeData); bool equip = CompareAndUpdateByteData(chara->EquipSlotData, chara->CustomizeData);
bool drawObj = (chara->GameObject.DrawObject != null && (IntPtr)chara->GameObject.DrawObject != DrawObjectAddress); bool drawObj = (IntPtr)chara->GameObject.DrawObject != DrawObjectAddress;
var name = new Utf8String(chara->GameObject.Name).ToString(); var name = new Utf8String(chara->GameObject.Name).ToString();
bool nameChange = (name != _name); bool nameChange = (name != _name);
if (addr || equip || drawObj || nameChange) if (addr || equip || drawObj || nameChange)
@@ -60,17 +60,11 @@ namespace MareSynchronos.Models
HasUnprocessedUpdate = true; HasUnprocessedUpdate = true;
} }
} }
else else if (Address != IntPtr.Zero || DrawObjectAddress != IntPtr.Zero)
{ {
if (Address != IntPtr.Zero || DrawObjectAddress != IntPtr.Zero)
{
Address = IntPtr.Zero;
DrawObjectAddress = IntPtr.Zero;
HasUnprocessedUpdate = true;
}
Address = IntPtr.Zero; Address = IntPtr.Zero;
DrawObjectAddress = IntPtr.Zero; DrawObjectAddress = IntPtr.Zero;
Logger.Verbose(ObjectKind + " Changed: " + _name + ", now: " + Address + ", " + DrawObjectAddress);
} }
} }
@@ -98,33 +92,30 @@ namespace MareSynchronos.Models
} }
} }
if (ObjectKind is not ObjectKind.Mount) var newHatState = Marshal.ReadByte((IntPtr)customizeData + 30, 0);
var newWeaponOrVisorState = Marshal.ReadByte((IntPtr)customizeData + 31, 0);
if (newHatState != HatState)
{ {
var newHatState = Marshal.ReadByte((IntPtr)customizeData + 30, 0); if (HatState != null && !hasChanges && !HasUnprocessedUpdate)
var newWeaponOrVisorState = Marshal.ReadByte((IntPtr)customizeData + 31, 0);
if (newHatState != HatState)
{ {
if (HatState != null && !hasChanges && !HasUnprocessedUpdate) Logger.Debug("Not Sending Update, only Hat changed");
{ DoNotSendUpdate = true;
Logger.Debug("Not Sending Update, only Hat changed");
DoNotSendUpdate = true;
}
HatState = newHatState;
hasChanges = true;
} }
HatState = newHatState;
hasChanges = true;
}
newWeaponOrVisorState &= 0b1101; // ignore drawing weapon newWeaponOrVisorState &= 0b1101; // ignore drawing weapon
if (newWeaponOrVisorState != VisorWeaponState) if (newWeaponOrVisorState != VisorWeaponState)
{
if (VisorWeaponState != null && !hasChanges && !HasUnprocessedUpdate)
{ {
if (VisorWeaponState != null && !hasChanges && !HasUnprocessedUpdate) Logger.Debug("Not Sending Update, only Visor/Weapon changed");
{ DoNotSendUpdate = true;
Logger.Debug("Not Sending Update, only Visor/Weapon changed");
DoNotSendUpdate = true;
}
VisorWeaponState = newWeaponOrVisorState;
hasChanges = true;
} }
VisorWeaponState = newWeaponOrVisorState;
hasChanges = true;
} }
return hasChanges; return hasChanges;

View File

@@ -13,6 +13,7 @@ using MareSynchronos.WebAPI;
using Dalamud.Interface.Windowing; using Dalamud.Interface.Windowing;
using MareSynchronos.UI; using MareSynchronos.UI;
using MareSynchronos.Utils; using MareSynchronos.Utils;
using System.Runtime.InteropServices;
namespace MareSynchronos namespace MareSynchronos
{ {
@@ -64,6 +65,10 @@ namespace MareSynchronos
_apiController = new ApiController(_configuration, _dalamudUtil); _apiController = new ApiController(_configuration, _dalamudUtil);
_ipcManager = new IpcManager(PluginInterface, _dalamudUtil); _ipcManager = new IpcManager(PluginInterface, _dalamudUtil);
// Compatibility for FileSystemWatchers under OSX
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
Environment.SetEnvironmentVariable("MONO_MANAGED_WATCHER", "enabled");
_fileCacheManager = new FileCacheManager(_ipcManager, _configuration); _fileCacheManager = new FileCacheManager(_ipcManager, _configuration);
_fileDialogManager = new FileDialogManager(); _fileDialogManager = new FileDialogManager();

View File

@@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Numerics; using System.Numerics;
using System.Reflection; using System.Reflection;
@@ -33,7 +34,13 @@ namespace MareSynchronos.UI
private float _windowContentWidth = 0; private float _windowContentWidth = 0;
public CompactUi(WindowSystem windowSystem, public CompactUi(WindowSystem windowSystem,
UiShared uiShared, Configuration configuration, ApiController apiController) : base("Mare Synchronos " + Assembly.GetExecutingAssembly().GetName().Version + "###MareSynchronosMainUI") UiShared uiShared, Configuration configuration, ApiController apiController)
#if DEBUG
: base("Mare Synchronos " + new FileInfo(Assembly.GetExecutingAssembly().Location) .LastWriteTime.ToString("yyyyMMddHHmmss")+ "###MareSynchronosMainUI")
#else
: base("Mare Synchronos " + Assembly.GetExecutingAssembly().GetName().Version + "###MareSynchronosMainUI")
#endif
{ {
Logger.Verbose("Creating " + nameof(CompactUi)); Logger.Verbose("Creating " + nameof(CompactUi));
@@ -132,7 +139,8 @@ namespace MareSynchronos.UI
var buttonSize = UiShared.GetIconButtonSize(pauseIcon); var buttonSize = UiShared.GetIconButtonSize(pauseIcon);
var trashButtonSize = UiShared.GetIconButtonSize(FontAwesomeIcon.Trash); var trashButtonSize = UiShared.GetIconButtonSize(FontAwesomeIcon.Trash);
var textSize = ImGui.CalcTextSize(entry.OtherUID); var entryUID = string.IsNullOrEmpty(entry.VanityUID) ? entry.OtherUID : entry.VanityUID;
var textSize = ImGui.CalcTextSize(entryUID);
var originalY = ImGui.GetCursorPosY(); var originalY = ImGui.GetCursorPosY();
var buttonSizes = buttonSize.Y + trashButtonSize.Y; var buttonSizes = buttonSize.Y + trashButtonSize.Y;
@@ -144,7 +152,7 @@ namespace MareSynchronos.UI
UiShared.ColorText(FontAwesomeIcon.ArrowUp.ToIconString(), ImGuiColors.DalamudRed); UiShared.ColorText(FontAwesomeIcon.ArrowUp.ToIconString(), ImGuiColors.DalamudRed);
ImGui.PopFont(); ImGui.PopFont();
UiShared.AttachToolTip(entry.OtherUID + " has not added you back"); UiShared.AttachToolTip(entryUID + " has not added you back");
} }
else if (entry.IsPaused || entry.IsPausedFromOthers) else if (entry.IsPaused || entry.IsPausedFromOthers)
{ {
@@ -152,7 +160,7 @@ namespace MareSynchronos.UI
UiShared.ColorText(FontAwesomeIcon.PauseCircle.ToIconString(), ImGuiColors.DalamudYellow); UiShared.ColorText(FontAwesomeIcon.PauseCircle.ToIconString(), ImGuiColors.DalamudYellow);
ImGui.PopFont(); ImGui.PopFont();
UiShared.AttachToolTip("Pairing status with " + entry.OtherUID + " is paused"); UiShared.AttachToolTip("Pairing status with " + entryUID + " is paused");
} }
else else
{ {
@@ -160,16 +168,16 @@ namespace MareSynchronos.UI
UiShared.ColorText(FontAwesomeIcon.Check.ToIconString(), ImGuiColors.ParsedGreen); UiShared.ColorText(FontAwesomeIcon.Check.ToIconString(), ImGuiColors.ParsedGreen);
ImGui.PopFont(); ImGui.PopFont();
UiShared.AttachToolTip("You are paired with " + entry.OtherUID); UiShared.AttachToolTip("You are paired with " + entryUID);
} }
var textIsUid = true; var textIsUid = true;
_showUidForEntry.TryGetValue(entry.OtherUID, out var showUidInsteadOfName); _showUidForEntry.TryGetValue(entry.OtherUID, out var showUidInsteadOfName);
if (!showUidInsteadOfName && _configuration.GetCurrentServerUidComments().TryGetValue(entry.OtherUID, out var playerText)) if (!showUidInsteadOfName && _configuration.GetCurrentServerUidComments().TryGetValue(entry.OtherUID, out var playerText))
{ {
if (playerText.IsNullOrEmpty()) if (string.IsNullOrEmpty(playerText))
{ {
playerText = entry.OtherUID; playerText = entryUID;
} }
else else
{ {
@@ -178,7 +186,7 @@ namespace MareSynchronos.UI
} }
else else
{ {
playerText = entry.OtherUID; playerText = entryUID;
} }
ImGui.SameLine(); ImGui.SameLine();
@@ -189,7 +197,7 @@ namespace MareSynchronos.UI
ImGui.TextUnformatted(playerText); ImGui.TextUnformatted(playerText);
if (textIsUid) ImGui.PopFont(); if (textIsUid) ImGui.PopFont();
UiShared.AttachToolTip("Left click to switch between UID display and nick" + Environment.NewLine + UiShared.AttachToolTip("Left click to switch between UID display and nick" + Environment.NewLine +
"Right click to change nick for " + entry.OtherUID); "Right click to change nick for " + entryUID);
if (ImGui.IsItemClicked(ImGuiMouseButton.Left)) if (ImGui.IsItemClicked(ImGuiMouseButton.Left))
{ {
var prevState = textIsUid; var prevState = textIsUid;
@@ -240,7 +248,7 @@ namespace MareSynchronos.UI
_apiController.PairedClients.Remove(entry); _apiController.PairedClients.Remove(entry);
} }
} }
UiShared.AttachToolTip("Hold CTRL and click to unpair permanently from " + entry.OtherUID); UiShared.AttachToolTip("Hold CTRL and click to unpair permanently from " + entryUID);
if (entry.IsSynced) if (entry.IsSynced)
{ {
@@ -251,8 +259,8 @@ namespace MareSynchronos.UI
_ = _apiController.SendPairedClientPauseChange(entry.OtherUID, !entry.IsPaused); _ = _apiController.SendPairedClientPauseChange(entry.OtherUID, !entry.IsPaused);
} }
UiShared.AttachToolTip(!entry.IsPaused UiShared.AttachToolTip(!entry.IsPaused
? "Pause pairing with " + entry.OtherUID ? "Pause pairing with " + entryUID
: "Resume pairing with " + entry.OtherUID); : "Resume pairing with " + entryUID);
} }
} }

View File

@@ -40,7 +40,6 @@ namespace MareSynchronos.UI
public static bool CtrlPressed() => (GetKeyState(0xA2) & 0x8000) != 0 || (GetKeyState(0xA3) & 0x8000) != 0; public static bool CtrlPressed() => (GetKeyState(0xA2) & 0x8000) != 0 || (GetKeyState(0xA3) & 0x8000) != 0;
// todo remove after rework
public ApiController ApiController => _apiController; public ApiController ApiController => _apiController;
public UiShared(IpcManager ipcManager, ApiController apiController, FileCacheManager fileCacheManager, FileDialogManager fileDialogManager, Configuration pluginConfiguration, DalamudUtil dalamudUtil, DalamudPluginInterface pluginInterface, Dalamud.Localization localization) public UiShared(IpcManager ipcManager, ApiController apiController, FileCacheManager fileCacheManager, FileDialogManager fileDialogManager, Configuration pluginConfiguration, DalamudUtil dalamudUtil, DalamudPluginInterface pluginInterface, Dalamud.Localization localization)

View File

@@ -74,7 +74,7 @@ namespace MareSynchronos.WebAPI
Logger.Debug("Downloading files (Download ID " + currentDownloadId + ")"); Logger.Debug("Downloading files (Download ID " + currentDownloadId + ")");
List<DownloadFileDto> downloadFileInfoFromService = new List<DownloadFileDto>(); List<DownloadFileDto> downloadFileInfoFromService = new List<DownloadFileDto>();
downloadFileInfoFromService.AddRange(await _mareHub!.InvokeAsync<List<DownloadFileDto>>(Api.InvokeGetFilesSizes, fileReplacementDto.Select(m => m.Hash).ToList(), ct)); downloadFileInfoFromService.AddRange(await _mareHub!.InvokeAsync<List<DownloadFileDto>>(Api.InvokeGetFilesSizes, fileReplacementDto.Select(f => f.Hash).ToList(), ct));
CurrentDownloads[currentDownloadId] = downloadFileInfoFromService.Distinct().Select(d => new DownloadFileTransfer(d)) CurrentDownloads[currentDownloadId] = downloadFileInfoFromService.Distinct().Select(d => new DownloadFileTransfer(d))
.Where(d => d.CanBeTransferred).ToList(); .Where(d => d.CanBeTransferred).ToList();

View File

@@ -68,6 +68,7 @@ namespace MareSynchronos.WebAPI
private void DalamudUtilOnLogOut() private void DalamudUtilOnLogOut()
{ {
Task.Run(async () => await StopConnection(_connectionCancellationTokenSource.Token)); Task.Run(async () => await StopConnection(_connectionCancellationTokenSource.Token));
ServerState = ServerState.Offline;
} }
private void DalamudUtilOnLogIn() private void DalamudUtilOnLogIn()
@@ -124,21 +125,34 @@ namespace MareSynchronos.WebAPI
private string ApiUri => _pluginConfiguration.ApiUri; private string ApiUri => _pluginConfiguration.ApiUri;
public int OnlineUsers => SystemInfoDto.OnlineUsers; public int OnlineUsers => SystemInfoDto.OnlineUsers;
public ServerState ServerState { get; private set; } private ServerState _serverState;
public ServerState ServerState
{
get => _serverState;
private set
{
Logger.Debug($"New ServerState: {value}, prev ServerState: {_serverState}");
_serverState = value;
}
}
public async Task CreateConnections() public async Task CreateConnections()
{ {
Logger.Info("Recreating Connection"); Logger.Debug("CreateConnections called");
await StopConnection(_connectionCancellationTokenSource.Token);
if (_pluginConfiguration.FullPause) if (_pluginConfiguration.FullPause)
{ {
Logger.Info("Not recreating Connection, paused");
ServerState = ServerState.Disconnected; ServerState = ServerState.Disconnected;
_connectionDto = null; _connectionDto = null;
await StopConnection(_connectionCancellationTokenSource.Token);
return; return;
} }
await StopConnection(_connectionCancellationTokenSource.Token);
Logger.Info("Recreating Connection");
_connectionCancellationTokenSource.Cancel(); _connectionCancellationTokenSource.Cancel();
_connectionCancellationTokenSource = new CancellationTokenSource(); _connectionCancellationTokenSource = new CancellationTokenSource();
var token = _connectionCancellationTokenSource.Token; var token = _connectionCancellationTokenSource.Token;
@@ -188,7 +202,6 @@ namespace MareSynchronos.WebAPI
await InitializeData(token); await InitializeData(token);
_mareHub.Closed += MareHubOnClosed; _mareHub.Closed += MareHubOnClosed;
_mareHub.Reconnected += MareHubOnReconnected;
_mareHub.Reconnecting += MareHubOnReconnecting; _mareHub.Reconnecting += MareHubOnReconnecting;
} }
} }
@@ -287,7 +300,7 @@ namespace MareSynchronos.WebAPI
.WithUrl(ApiUri + hubName, options => .WithUrl(ApiUri + hubName, options =>
{ {
options.Headers.Add("Authorization", SecretKey); options.Headers.Add("Authorization", SecretKey);
options.Transports = HttpTransportType.WebSockets; options.Transports = HttpTransportType.WebSockets | HttpTransportType.ServerSentEvents | HttpTransportType.LongPolling;
}) })
.WithAutomaticReconnect(new ForeverRetryPolicy()) .WithAutomaticReconnect(new ForeverRetryPolicy())
.Build(); .Build();
@@ -298,30 +311,21 @@ namespace MareSynchronos.WebAPI
CurrentUploads.Clear(); CurrentUploads.Clear();
CurrentDownloads.Clear(); CurrentDownloads.Clear();
_uploadCancellationTokenSource?.Cancel(); _uploadCancellationTokenSource?.Cancel();
Logger.Info("Connection closed");
Disconnected?.Invoke(); Disconnected?.Invoke();
ServerState = ServerState.Offline; ServerState = ServerState.Offline;
Logger.Info("Connection closed");
return Task.CompletedTask; return Task.CompletedTask;
} }
private async Task MareHubOnReconnected(string? arg)
{
Logger.Info("Connection restored");
await Task.Delay(TimeSpan.FromSeconds(new Random().Next(5, 10)));
_ = Task.Run(CreateConnections);
}
private Task MareHubOnReconnecting(Exception? arg) private Task MareHubOnReconnecting(Exception? arg)
{ {
CurrentUploads.Clear();
CurrentDownloads.Clear();
_uploadCancellationTokenSource?.Cancel();
ServerState = ServerState.Disconnected; ServerState = ServerState.Disconnected;
Logger.Warn("Connection closed... Reconnecting"); Logger.Warn("Connection closed... Reconnecting");
Logger.Warn(arg?.Message ?? string.Empty); Logger.Warn(arg?.Message ?? string.Empty);
Logger.Warn(arg?.StackTrace ?? string.Empty); Logger.Warn(arg?.StackTrace ?? string.Empty);
Disconnected?.Invoke(); Disconnected?.Invoke();
ServerState = ServerState.Offline;
_ = Task.Run(CreateConnections);
return Task.CompletedTask; return Task.CompletedTask;
} }
@@ -331,13 +335,24 @@ namespace MareSynchronos.WebAPI
{ {
_uploadCancellationTokenSource?.Cancel(); _uploadCancellationTokenSource?.Cancel();
Logger.Info("Stopping existing connection"); Logger.Info("Stopping existing connection");
await _mareHub.StopAsync(token);
_mareHub.Closed -= MareHubOnClosed; _mareHub.Closed -= MareHubOnClosed;
_mareHub.Reconnected -= MareHubOnReconnected;
_mareHub.Reconnecting += MareHubOnReconnecting; _mareHub.Reconnecting += MareHubOnReconnecting;
await _mareHub.StopAsync(token);
await _mareHub.DisposeAsync(); await _mareHub.DisposeAsync();
CurrentUploads.Clear();
CurrentDownloads.Clear();
_uploadCancellationTokenSource?.Cancel();
Disconnected?.Invoke();
_mareHub = null; _mareHub = null;
} }
if (ServerState != ServerState.Disconnected)
{
while (ServerState != ServerState.Offline)
{
await Task.Delay(16);
}
}
} }
} }
} }