merge from main
This commit is contained in:
@@ -33,14 +33,26 @@ public class CharacterDataFactory
|
||||
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)
|
||||
{
|
||||
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);
|
||||
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)
|
||||
{
|
||||
if (texPath.IsNullOrEmpty()) return;
|
||||
if (string.IsNullOrEmpty(texPath)) return;
|
||||
|
||||
//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)
|
||||
{
|
||||
if (previousData.FileReplacements.ContainsKey(objectKind))
|
||||
{
|
||||
previousData.FileReplacements[objectKind].Clear();
|
||||
}
|
||||
|
||||
Stopwatch st = Stopwatch.StartNew();
|
||||
var chara = _dalamudUtil.CreateGameObject(charaPointer)!;
|
||||
while (!_dalamudUtil.IsObjectPresent(chara))
|
||||
@@ -229,17 +246,9 @@ public class CharacterDataFactory
|
||||
}
|
||||
_dalamudUtil.WaitWhileCharacterIsDrawing(charaPointer);
|
||||
|
||||
if (previousData.FileReplacements.ContainsKey(objectKind))
|
||||
{
|
||||
previousData.FileReplacements[objectKind].Clear();
|
||||
}
|
||||
|
||||
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();
|
||||
for (var mdlIdx = 0; mdlIdx < human->CharacterBase.SlotCount; ++mdlIdx)
|
||||
|
||||
@@ -9,9 +9,9 @@ using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
||||
using MareSynchronos.API;
|
||||
using MareSynchronos.FileCacheDB;
|
||||
using MareSynchronos.Interop;
|
||||
using MareSynchronos.Models;
|
||||
using MareSynchronos.Utils;
|
||||
using MareSynchronos.WebAPI;
|
||||
using Penumbra.GameData.Structs;
|
||||
|
||||
namespace MareSynchronos.Managers;
|
||||
|
||||
@@ -59,7 +59,7 @@ public class CachedPlayer
|
||||
|
||||
private CharacterCacheDto _cachedData = new();
|
||||
|
||||
private CharacterEquipment? _currentCharacterEquipment;
|
||||
private PlayerRelatedObject? _currentCharacterEquipment;
|
||||
|
||||
public void ApplyCharacterData(CharacterCacheDto characterData)
|
||||
{
|
||||
@@ -235,15 +235,29 @@ public class CachedPlayer
|
||||
RequestedPenumbraRedraw = true;
|
||||
Logger.Debug(
|
||||
$"Request Redraw for {PlayerName}");
|
||||
_ipcManager.GlamourerApplyAll(glamourerData, PlayerCharacter.Address);
|
||||
}
|
||||
else if (objectKind == ObjectKind.Minion)
|
||||
{
|
||||
var minion = ((Character*)PlayerCharacter.Address)->CompanionObject;
|
||||
if (minion != null)
|
||||
if (_ipcManager.CheckGlamourerApi() && !string.IsNullOrEmpty(glamourerData))
|
||||
{
|
||||
Logger.Debug($"Request Redraw for Minion");
|
||||
_ipcManager.GlamourerApplyAll(glamourerData, obj: (IntPtr)minion);
|
||||
_ipcManager.GlamourerApplyAll(glamourerData, PlayerCharacter.Address);
|
||||
}
|
||||
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)
|
||||
@@ -252,7 +266,14 @@ public class CachedPlayer
|
||||
if (pet != IntPtr.Zero)
|
||||
{
|
||||
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)
|
||||
@@ -261,16 +282,14 @@ public class CachedPlayer
|
||||
if (companion != IntPtr.Zero)
|
||||
{
|
||||
Logger.Debug("Request Redraw for Companion");
|
||||
_ipcManager.GlamourerApplyAll(glamourerData, companion);
|
||||
}
|
||||
}
|
||||
else if (objectKind == ObjectKind.Mount)
|
||||
{
|
||||
var mount = ((CharaExt*)PlayerCharacter.Address)->Mount;
|
||||
if (mount != null)
|
||||
{
|
||||
Logger.Debug($"Request Redraw for Mount");
|
||||
_ipcManager.PenumbraRedraw((IntPtr)mount);
|
||||
if (_ipcManager.CheckGlamourerApi() && !string.IsNullOrEmpty(glamourerData))
|
||||
{
|
||||
_ipcManager.GlamourerApplyAll(glamourerData, companion);
|
||||
}
|
||||
else
|
||||
{
|
||||
_ipcManager.PenumbraRedraw(companion);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -281,15 +300,22 @@ public class CachedPlayer
|
||||
|
||||
if (objectKind == ObjectKind.Player)
|
||||
{
|
||||
_ipcManager.GlamourerApplyOnlyCustomization(_originalGlamourerData, PlayerCharacter);
|
||||
_ipcManager.GlamourerApplyOnlyEquipment(_lastGlamourerData, PlayerCharacter);
|
||||
}
|
||||
else if (objectKind == ObjectKind.Minion)
|
||||
{
|
||||
var minion = ((Character*)PlayerCharacter.Address)->CompanionObject;
|
||||
if (minion != null)
|
||||
if (_ipcManager.CheckGlamourerApi())
|
||||
{
|
||||
_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)
|
||||
@@ -308,14 +334,6 @@ public class CachedPlayer
|
||||
_ipcManager.PenumbraRedraw(companion);
|
||||
}
|
||||
}
|
||||
else if (objectKind == ObjectKind.Mount)
|
||||
{
|
||||
var mount = ((CharaExt*)PlayerCharacter.Address)->Mount;
|
||||
if (mount != null)
|
||||
{
|
||||
_ipcManager.PenumbraRedraw((IntPtr)mount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void DisposePlayer()
|
||||
@@ -363,7 +381,8 @@ public class CachedPlayer
|
||||
_dalamudUtil.FrameworkUpdate += DalamudUtilOnFrameworkUpdate;
|
||||
_ipcManager.PenumbraRedrawEvent += IpcManagerOnPenumbraRedrawEvent;
|
||||
_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;
|
||||
if (cache != null)
|
||||
{
|
||||
@@ -382,7 +401,8 @@ public class CachedPlayer
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_currentCharacterEquipment!.CompareAndUpdate(PlayerCharacter))
|
||||
_currentCharacterEquipment?.CheckAndUpdateObject();
|
||||
if (_currentCharacterEquipment?.HasUnprocessedUpdate ?? false)
|
||||
{
|
||||
OnPlayerChanged();
|
||||
}
|
||||
@@ -406,7 +426,9 @@ public class CachedPlayer
|
||||
_penumbraRedrawEventTask = Task.Run(() =>
|
||||
{
|
||||
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)
|
||||
{
|
||||
@@ -425,6 +447,7 @@ public class CachedPlayer
|
||||
private void OnPlayerChanged()
|
||||
{
|
||||
Logger.Debug($"Player {PlayerName} changed, PenumbraRedraw is {RequestedPenumbraRedraw}");
|
||||
_currentCharacterEquipment!.HasUnprocessedUpdate = false;
|
||||
if (!RequestedPenumbraRedraw && PlayerCharacter is not null)
|
||||
{
|
||||
Logger.Debug($"Saving new Glamourer data");
|
||||
|
||||
@@ -158,12 +158,19 @@ namespace MareSynchronos.Managers
|
||||
public string GlamourerGetCharacterCustomization(GameObject character)
|
||||
{
|
||||
if (!CheckGlamourerApi()) return string.Empty;
|
||||
var glamourerString = _glamourerGetAllCustomization!.InvokeFunc(character);
|
||||
byte[] bytes = Convert.FromBase64String(glamourerString);
|
||||
// ignore transparency
|
||||
bytes[88] = 128;
|
||||
bytes[89] = 63;
|
||||
return Convert.ToBase64String(bytes);
|
||||
try
|
||||
{
|
||||
var glamourerString = _glamourerGetAllCustomization!.InvokeFunc(character);
|
||||
byte[] bytes = Convert.FromBase64String(glamourerString);
|
||||
// ignore transparency
|
||||
bytes[88] = 128;
|
||||
bytes[89] = 63;
|
||||
return Convert.ToBase64String(bytes);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public void GlamourerRevertCharacterCustomization(GameObject character)
|
||||
|
||||
@@ -5,12 +5,10 @@ using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MareSynchronos.API;
|
||||
using Penumbra.GameData.Structs;
|
||||
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using MareSynchronos.Models;
|
||||
using MareSynchronos.Interop;
|
||||
|
||||
namespace MareSynchronos.Managers
|
||||
{
|
||||
@@ -30,7 +28,6 @@ namespace MareSynchronos.Managers
|
||||
|
||||
private CancellationTokenSource? _playerChangedCts = new();
|
||||
private DateTime _lastPlayerObjectCheck;
|
||||
private CharacterEquipment? _currentCharacterEquipment = new();
|
||||
|
||||
private List<PlayerRelatedObject> playerRelatedObjects = new List<PlayerRelatedObject>();
|
||||
|
||||
@@ -58,10 +55,9 @@ namespace MareSynchronos.Managers
|
||||
playerRelatedObjects = new List<PlayerRelatedObject>()
|
||||
{
|
||||
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.Companion, IntPtr.Zero, IntPtr.Zero, () => _dalamudUtil.GetCompanion()),
|
||||
new PlayerRelatedObject(ObjectKind.Mount, IntPtr.Zero, IntPtr.Zero, () => (IntPtr)((CharaExt*)_dalamudUtil.PlayerPointer)->Mount),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<Authors></Authors>
|
||||
<Company></Company>
|
||||
<Version>0.3.4</Version>
|
||||
<Version>0.3.10</Version>
|
||||
<Description></Description>
|
||||
<Copyright></Copyright>
|
||||
<PackageProjectUrl>https://github.com/Penumbra-Sync/client</PackageProjectUrl>
|
||||
@@ -21,12 +21,12 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<DalamudLibPath>$(appdata)\XIVLauncher\addon\Hooks\dev\</DalamudLibPath>
|
||||
<DalamudLibPath>$(appdata)\XIVLauncher\addon\Hooks\Dev\</DalamudLibPath>
|
||||
<AssemblyVersion></AssemblyVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<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="Microsoft.AspNetCore.SignalR.Client" Version="6.0.8" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.8" />
|
||||
@@ -84,7 +84,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
|
||||
<Exec Command="rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\alpine-x64
rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\linux-arm
rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\linux-arm64
rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\linux-armel
rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\linux-mips64
rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\linux-musl-x64
rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\linux-x64
rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\linux-x86
rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\osx-x64
rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\win-arm
rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\win-arm64
if $(ConfigurationName) == Debug (
del /Q $(ProjectDir)$(OutDir)Mare.7z
"C:\Program Files\7-zip\7z.exe" a $(ProjectDir)$(OutDir)Mare.7z $(ProjectDir)$(OutDir)*
)" />
|
||||
<Exec Command="rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\alpine-x64
rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\linux-arm
rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\linux-arm64
rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\linux-armel
rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\linux-mips64
rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\linux-musl-x64
rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\linux-x64
rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\linux-x86
rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\linux-s390x
rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\osx-x64
rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\osx-arm64
rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\win-arm
rmdir /S /Q $(ProjectDir)$(OutDir)runtimes\win-arm64
if $(ConfigurationName) == Debug (
del /Q $(ProjectDir)$(OutDir)Mare.7z
"C:\Program Files\7-zip\7z.exe" a $(ProjectDir)$(OutDir)Mare.7z $(ProjectDir)$(OutDir)*
)" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace MareSynchronos.Models
|
||||
var chara = (Character*)curPtr;
|
||||
bool addr = Address == IntPtr.Zero || Address != curPtr;
|
||||
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();
|
||||
bool nameChange = (name != _name);
|
||||
if (addr || equip || drawObj || nameChange)
|
||||
@@ -60,17 +60,11 @@ namespace MareSynchronos.Models
|
||||
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;
|
||||
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);
|
||||
var newWeaponOrVisorState = Marshal.ReadByte((IntPtr)customizeData + 31, 0);
|
||||
if (newHatState != HatState)
|
||||
if (HatState != null && !hasChanges && !HasUnprocessedUpdate)
|
||||
{
|
||||
if (HatState != null && !hasChanges && !HasUnprocessedUpdate)
|
||||
{
|
||||
Logger.Debug("Not Sending Update, only Hat changed");
|
||||
DoNotSendUpdate = true;
|
||||
}
|
||||
HatState = newHatState;
|
||||
hasChanges = true;
|
||||
Logger.Debug("Not Sending Update, only Hat changed");
|
||||
DoNotSendUpdate = 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;
|
||||
}
|
||||
VisorWeaponState = newWeaponOrVisorState;
|
||||
hasChanges = true;
|
||||
Logger.Debug("Not Sending Update, only Visor/Weapon changed");
|
||||
DoNotSendUpdate = true;
|
||||
}
|
||||
VisorWeaponState = newWeaponOrVisorState;
|
||||
hasChanges = true;
|
||||
}
|
||||
|
||||
return hasChanges;
|
||||
|
||||
@@ -13,6 +13,7 @@ using MareSynchronos.WebAPI;
|
||||
using Dalamud.Interface.Windowing;
|
||||
using MareSynchronos.UI;
|
||||
using MareSynchronos.Utils;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace MareSynchronos
|
||||
{
|
||||
@@ -64,6 +65,10 @@ namespace MareSynchronos
|
||||
_apiController = new ApiController(_configuration, _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);
|
||||
_fileDialogManager = new FileDialogManager();
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Reflection;
|
||||
@@ -33,7 +34,13 @@ namespace MareSynchronos.UI
|
||||
private float _windowContentWidth = 0;
|
||||
|
||||
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));
|
||||
|
||||
@@ -132,7 +139,8 @@ namespace MareSynchronos.UI
|
||||
|
||||
var buttonSize = UiShared.GetIconButtonSize(pauseIcon);
|
||||
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 buttonSizes = buttonSize.Y + trashButtonSize.Y;
|
||||
|
||||
@@ -144,7 +152,7 @@ namespace MareSynchronos.UI
|
||||
UiShared.ColorText(FontAwesomeIcon.ArrowUp.ToIconString(), ImGuiColors.DalamudRed);
|
||||
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)
|
||||
{
|
||||
@@ -152,7 +160,7 @@ namespace MareSynchronos.UI
|
||||
UiShared.ColorText(FontAwesomeIcon.PauseCircle.ToIconString(), ImGuiColors.DalamudYellow);
|
||||
ImGui.PopFont();
|
||||
|
||||
UiShared.AttachToolTip("Pairing status with " + entry.OtherUID + " is paused");
|
||||
UiShared.AttachToolTip("Pairing status with " + entryUID + " is paused");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -160,16 +168,16 @@ namespace MareSynchronos.UI
|
||||
UiShared.ColorText(FontAwesomeIcon.Check.ToIconString(), ImGuiColors.ParsedGreen);
|
||||
ImGui.PopFont();
|
||||
|
||||
UiShared.AttachToolTip("You are paired with " + entry.OtherUID);
|
||||
UiShared.AttachToolTip("You are paired with " + entryUID);
|
||||
}
|
||||
|
||||
var textIsUid = true;
|
||||
_showUidForEntry.TryGetValue(entry.OtherUID, out var showUidInsteadOfName);
|
||||
if (!showUidInsteadOfName && _configuration.GetCurrentServerUidComments().TryGetValue(entry.OtherUID, out var playerText))
|
||||
{
|
||||
if (playerText.IsNullOrEmpty())
|
||||
if (string.IsNullOrEmpty(playerText))
|
||||
{
|
||||
playerText = entry.OtherUID;
|
||||
playerText = entryUID;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -178,7 +186,7 @@ namespace MareSynchronos.UI
|
||||
}
|
||||
else
|
||||
{
|
||||
playerText = entry.OtherUID;
|
||||
playerText = entryUID;
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
@@ -189,7 +197,7 @@ namespace MareSynchronos.UI
|
||||
ImGui.TextUnformatted(playerText);
|
||||
if (textIsUid) ImGui.PopFont();
|
||||
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))
|
||||
{
|
||||
var prevState = textIsUid;
|
||||
@@ -240,7 +248,7 @@ namespace MareSynchronos.UI
|
||||
_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)
|
||||
{
|
||||
@@ -251,8 +259,8 @@ namespace MareSynchronos.UI
|
||||
_ = _apiController.SendPairedClientPauseChange(entry.OtherUID, !entry.IsPaused);
|
||||
}
|
||||
UiShared.AttachToolTip(!entry.IsPaused
|
||||
? "Pause pairing with " + entry.OtherUID
|
||||
: "Resume pairing with " + entry.OtherUID);
|
||||
? "Pause pairing with " + entryUID
|
||||
: "Resume pairing with " + entryUID);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,6 @@ namespace MareSynchronos.UI
|
||||
|
||||
public static bool CtrlPressed() => (GetKeyState(0xA2) & 0x8000) != 0 || (GetKeyState(0xA3) & 0x8000) != 0;
|
||||
|
||||
// todo remove after rework
|
||||
public ApiController ApiController => _apiController;
|
||||
|
||||
public UiShared(IpcManager ipcManager, ApiController apiController, FileCacheManager fileCacheManager, FileDialogManager fileDialogManager, Configuration pluginConfiguration, DalamudUtil dalamudUtil, DalamudPluginInterface pluginInterface, Dalamud.Localization localization)
|
||||
|
||||
@@ -74,7 +74,7 @@ namespace MareSynchronos.WebAPI
|
||||
Logger.Debug("Downloading files (Download ID " + currentDownloadId + ")");
|
||||
|
||||
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))
|
||||
.Where(d => d.CanBeTransferred).ToList();
|
||||
|
||||
@@ -68,6 +68,7 @@ namespace MareSynchronos.WebAPI
|
||||
private void DalamudUtilOnLogOut()
|
||||
{
|
||||
Task.Run(async () => await StopConnection(_connectionCancellationTokenSource.Token));
|
||||
ServerState = ServerState.Offline;
|
||||
}
|
||||
|
||||
private void DalamudUtilOnLogIn()
|
||||
@@ -124,21 +125,34 @@ namespace MareSynchronos.WebAPI
|
||||
private string ApiUri => _pluginConfiguration.ApiUri;
|
||||
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()
|
||||
{
|
||||
Logger.Info("Recreating Connection");
|
||||
|
||||
await StopConnection(_connectionCancellationTokenSource.Token);
|
||||
Logger.Debug("CreateConnections called");
|
||||
|
||||
if (_pluginConfiguration.FullPause)
|
||||
{
|
||||
Logger.Info("Not recreating Connection, paused");
|
||||
ServerState = ServerState.Disconnected;
|
||||
_connectionDto = null;
|
||||
await StopConnection(_connectionCancellationTokenSource.Token);
|
||||
return;
|
||||
}
|
||||
|
||||
await StopConnection(_connectionCancellationTokenSource.Token);
|
||||
|
||||
Logger.Info("Recreating Connection");
|
||||
|
||||
_connectionCancellationTokenSource.Cancel();
|
||||
_connectionCancellationTokenSource = new CancellationTokenSource();
|
||||
var token = _connectionCancellationTokenSource.Token;
|
||||
@@ -188,7 +202,6 @@ namespace MareSynchronos.WebAPI
|
||||
await InitializeData(token);
|
||||
|
||||
_mareHub.Closed += MareHubOnClosed;
|
||||
_mareHub.Reconnected += MareHubOnReconnected;
|
||||
_mareHub.Reconnecting += MareHubOnReconnecting;
|
||||
}
|
||||
}
|
||||
@@ -287,7 +300,7 @@ namespace MareSynchronos.WebAPI
|
||||
.WithUrl(ApiUri + hubName, options =>
|
||||
{
|
||||
options.Headers.Add("Authorization", SecretKey);
|
||||
options.Transports = HttpTransportType.WebSockets;
|
||||
options.Transports = HttpTransportType.WebSockets | HttpTransportType.ServerSentEvents | HttpTransportType.LongPolling;
|
||||
})
|
||||
.WithAutomaticReconnect(new ForeverRetryPolicy())
|
||||
.Build();
|
||||
@@ -298,30 +311,21 @@ namespace MareSynchronos.WebAPI
|
||||
CurrentUploads.Clear();
|
||||
CurrentDownloads.Clear();
|
||||
_uploadCancellationTokenSource?.Cancel();
|
||||
Logger.Info("Connection closed");
|
||||
Disconnected?.Invoke();
|
||||
ServerState = ServerState.Offline;
|
||||
Logger.Info("Connection closed");
|
||||
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)
|
||||
{
|
||||
CurrentUploads.Clear();
|
||||
CurrentDownloads.Clear();
|
||||
_uploadCancellationTokenSource?.Cancel();
|
||||
ServerState = ServerState.Disconnected;
|
||||
Logger.Warn("Connection closed... Reconnecting");
|
||||
Logger.Warn(arg?.Message ?? string.Empty);
|
||||
Logger.Warn(arg?.StackTrace ?? string.Empty);
|
||||
Disconnected?.Invoke();
|
||||
ServerState = ServerState.Offline;
|
||||
_ = Task.Run(CreateConnections);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
@@ -331,13 +335,24 @@ namespace MareSynchronos.WebAPI
|
||||
{
|
||||
_uploadCancellationTokenSource?.Cancel();
|
||||
Logger.Info("Stopping existing connection");
|
||||
await _mareHub.StopAsync(token);
|
||||
_mareHub.Closed -= MareHubOnClosed;
|
||||
_mareHub.Reconnected -= MareHubOnReconnected;
|
||||
_mareHub.Reconnecting += MareHubOnReconnecting;
|
||||
await _mareHub.StopAsync(token);
|
||||
await _mareHub.DisposeAsync();
|
||||
CurrentUploads.Clear();
|
||||
CurrentDownloads.Clear();
|
||||
_uploadCancellationTokenSource?.Cancel();
|
||||
Disconnected?.Invoke();
|
||||
_mareHub = null;
|
||||
}
|
||||
|
||||
if (ServerState != ServerState.Disconnected)
|
||||
{
|
||||
while (ServerState != ServerState.Offline)
|
||||
{
|
||||
await Task.Delay(16);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user