Lightless Lightfinder redesign + stuff #127

Merged
choco merged 43 commits from 2.0.0-crashing-bugfixes into 2.0.3 2026-01-04 14:21:29 +00:00
24 changed files with 362 additions and 124 deletions
Showing only changes of commit 754df95071 - Show all commits

3
.gitignore vendored
View File

@@ -348,3 +348,6 @@ MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# idea
/.idea

View File

@@ -85,7 +85,7 @@ public sealed class TransientResourceManager : DisposableMediatorSubscriberBase
}
}
private string PlayerPersistentDataKey => _dalamudUtil.GetPlayerNameAsync().GetAwaiter().GetResult() + "_" + _dalamudUtil.GetHomeWorldIdAsync().GetAwaiter().GetResult();
private string PlayerPersistentDataKey => _dalamudUtil.GetPlayerName() + "_" + _dalamudUtil.GetHomeWorldId();
private ConcurrentDictionary<ObjectKind, HashSet<string>> SemiTransientResources
{
get

View File

@@ -52,7 +52,7 @@ public sealed class Plugin : IDalamudPlugin
IFramework framework, IObjectTable objectTable, IClientState clientState, ICondition condition, IChatGui chatGui,
IGameGui gameGui, IDtrBar dtrBar, IPluginLog pluginLog, ITargetManager targetManager, INotificationManager notificationManager,
ITextureProvider textureProvider, IContextMenu contextMenu, IGameInteropProvider gameInteropProvider, IGameConfig gameConfig,
ISigScanner sigScanner, INamePlateGui namePlateGui, IAddonLifecycle addonLifecycle)
ISigScanner sigScanner, INamePlateGui namePlateGui, IAddonLifecycle addonLifecycle, IPlayerState playerState)
{
NativeDll.Initialize(pluginInterface.AssemblyLocation.DirectoryName);
if (!Directory.Exists(pluginInterface.ConfigDirectory.FullName))
@@ -140,6 +140,7 @@ public sealed class Plugin : IDalamudPlugin
services.AddSingleton<IdDisplayHandler>();
services.AddSingleton<PlayerPerformanceService>();
services.AddSingleton<PenumbraTempCollectionJanitor>();
services.AddSingleton<LocationShareService>();
services.AddSingleton<TextureMetadataHelper>(sp =>
new TextureMetadataHelper(sp.GetRequiredService<ILogger<TextureMetadataHelper>>(), gameData));
@@ -219,6 +220,7 @@ public sealed class Plugin : IDalamudPlugin
gameData,
targetManager,
gameConfig,
playerState,
sp.GetRequiredService<ActorObjectService>(),
sp.GetRequiredService<BlockedCharacterHandler>(),
sp.GetRequiredService<LightlessMediator>(),

View File

@@ -450,7 +450,7 @@ public class CharaDataGposeTogetherManager : DisposableMediatorSubscriberBase
};
}
var loc = await _dalamudUtil.GetMapDataAsync().ConfigureAwait(false);
var loc = _dalamudUtil.GetMapData();
worldData.LocationInfo = loc;
if (_forceResendWorldData || worldData != _lastWorldData)

View File

@@ -254,7 +254,7 @@ public sealed partial class CharaDataManager : DisposableMediatorSubscriberBase
Logger.LogTrace("Attaching World data {data}", worldData);
worldData.LocationInfo = await _dalamudUtilService.GetMapDataAsync().ConfigureAwait(false);
worldData.LocationInfo = _dalamudUtilService.GetMapData();
Logger.LogTrace("World data serialized: {data}", worldData);

View File

@@ -186,8 +186,8 @@ public sealed class CharaDataNearbyManager : DisposableMediatorSubscriberBase
var previousPoses = _nearbyData.Keys.ToList();
_nearbyData.Clear();
var ownLocation = await _dalamudUtilService.RunOnFrameworkThread(() => _dalamudUtilService.GetMapData()).ConfigureAwait(false);
var player = await _dalamudUtilService.RunOnFrameworkThread(() => _dalamudUtilService.GetPlayerCharacter()).ConfigureAwait(false);
var ownLocation = _dalamudUtilService.GetMapData();
var player = await _dalamudUtilService.GetPlayerCharacterAsync().ConfigureAwait(false);
var currentServer = player.CurrentWorld;
var playerPos = player.Position;

View File

@@ -576,7 +576,7 @@ public sealed class ZoneChatService : DisposableMediatorSubscriberBase, IHostedS
try
{
var location = await _dalamudUtilService.GetMapDataAsync().ConfigureAwait(false);
var location = _dalamudUtilService.GetMapData();
var territoryId = (ushort)location.TerritoryId;
var worldId = (ushort)location.ServerId;
@@ -702,7 +702,7 @@ public sealed class ZoneChatService : DisposableMediatorSubscriberBase, IHostedS
{
try
{
var worldId = (ushort)await _dalamudUtilService.GetWorldIdAsync().ConfigureAwait(false);
var worldId = (ushort)_dalamudUtilService.GetWorldId();
return definition.Descriptor with { WorldId = worldId };
}
catch (Exception ex)
@@ -1161,7 +1161,7 @@ public sealed class ZoneChatService : DisposableMediatorSubscriberBase, IHostedS
{
try
{
return _dalamudUtilService.GetPlayerNameAsync().ConfigureAwait(false).GetAwaiter().GetResult();
return _dalamudUtilService.GetPlayerName();
}
catch (Exception ex)
{

View File

@@ -241,7 +241,7 @@ internal class ContextMenuService : IHostedService
return;
}
var senderCid = (await _dalamudUtil.GetCIDAsync().ConfigureAwait(false)).ToString().GetHash256();
var senderCid = _dalamudUtil.GetCID().ToString().GetHash256();
var receiverCid = DalamudUtilService.GetHashedCIDFromPlayerPointer(targetData.Address);
_logger.LogInformation("Sending pair request: sender {SenderCid}, receiver {ReceiverCid}", senderCid, receiverCid);

View File

@@ -1,11 +1,13 @@
using Dalamud.Game.ClientState.Conditions;
using Dalamud.Game.ClientState.Objects.SubKinds;
using Dalamud.Game.ClientState.Objects.Types;
using Dalamud.Game.Text;
using Dalamud.Plugin.Services;
using Dalamud.Utility;
using FFXIVClientStructs.FFXIV.Client.Game;
using FFXIVClientStructs.FFXIV.Client.Game.Character;
using FFXIVClientStructs.FFXIV.Client.Game.Control;
using FFXIVClientStructs.FFXIV.Client.Game.UI;
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
using LightlessSync.API.Dto.CharaData;
@@ -26,6 +28,7 @@ using System.Text;
using BattleNpcSubKind = FFXIVClientStructs.FFXIV.Client.Game.Object.BattleNpcSubKind;
using DalamudObjectKind = Dalamud.Game.ClientState.Objects.Enums.ObjectKind;
using GameObject = FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject;
using Map = Lumina.Excel.Sheets.Map;
using VisibilityFlags = FFXIVClientStructs.FFXIV.Client.Game.Object.VisibilityFlags;
namespace LightlessSync.Services;
@@ -37,6 +40,7 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
private readonly ICondition _condition;
private readonly IDataManager _gameData;
private readonly IGameConfig _gameConfig;
private readonly IPlayerState _playerState;
private readonly BlockedCharacterHandler _blockedCharacterHandler;
private readonly IFramework _framework;
private readonly IGameGui _gameGui;
@@ -60,7 +64,7 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
private Lazy<ulong> _cid;
public DalamudUtilService(ILogger<DalamudUtilService> logger, IClientState clientState, IObjectTable objectTable, IFramework framework,
IGameGui gameGui, ICondition condition, IDataManager gameData, ITargetManager targetManager, IGameConfig gameConfig,
IGameGui gameGui, ICondition condition, IDataManager gameData, ITargetManager targetManager, IGameConfig gameConfig, IPlayerState playerState,
ActorObjectService actorObjectService, BlockedCharacterHandler blockedCharacterHandler, LightlessMediator mediator, PerformanceCollectorService performanceCollector,
LightlessConfigService configService, PlayerPerformanceConfigService playerPerformanceConfigService, Lazy<PairFactory> pairFactory)
{
@@ -72,6 +76,7 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
_condition = condition;
_gameData = gameData;
_gameConfig = gameConfig;
_playerState = playerState;
_actorObjectService = actorObjectService;
_targetManager = targetManager;
_blockedCharacterHandler = blockedCharacterHandler;
@@ -95,6 +100,12 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
TerritoryData = new(() => BuildTerritoryData(clientLanguage));
TerritoryDataEnglish = new(() => BuildTerritoryData(Dalamud.Game.ClientLanguage.English));
MapData = new(() => BuildMapData(clientLanguage));
ContentFinderData = new Lazy<Dictionary<uint, string>>(() =>
{
return _gameData.GetExcelSheet<TerritoryType>()!
.Where(w => w.RowId != 0 && !string.IsNullOrEmpty(w.ContentFinderCondition.ValueNullable?.Name.ToString()))
.ToDictionary(w => w.RowId, w => w.ContentFinderCondition.Value.Name.ToString());
});
mediator.Subscribe<TargetPairMessage>(this, (msg) =>
{
if (clientState.IsPvP) return;
@@ -280,6 +291,7 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
public Lazy<Dictionary<uint, string>> TerritoryData { get; private set; }
public Lazy<Dictionary<uint, string>> TerritoryDataEnglish { get; private set; }
public Lazy<Dictionary<uint, (Map Map, string MapName)>> MapData { get; private set; }
public Lazy<Dictionary<uint, string>> ContentFinderData { get; private set; }
public bool IsLodEnabled { get; private set; }
public LightlessMediator Mediator { get; }
@@ -373,7 +385,7 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
public bool GetIsPlayerPresent()
{
EnsureIsOnFramework();
return _objectTable.LocalPlayer != null && _objectTable.LocalPlayer.IsValid();
return _objectTable.LocalPlayer != null && _objectTable.LocalPlayer.IsValid() && _playerState.IsLoaded;
}
public async Task<bool> GetIsPlayerPresentAsync()
@@ -587,34 +599,17 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
public string GetPlayerName()
{
EnsureIsOnFramework();
return _objectTable.LocalPlayer?.Name.ToString() ?? "--";
}
public async Task<string> GetPlayerNameAsync()
{
return await RunOnFrameworkThread(GetPlayerName).ConfigureAwait(false);
}
public async Task<ulong> GetCIDAsync()
{
return await RunOnFrameworkThread(GetCID).ConfigureAwait(false);
return _playerState.CharacterName;
}
public unsafe ulong GetCID()
{
EnsureIsOnFramework();
var playerChar = GetPlayerCharacter();
if (playerChar == null || playerChar.Address == IntPtr.Zero)
return 0;
return ((BattleChara*)playerChar.Address)->Character.ContentId;
return _playerState.ContentId;
}
public async Task<string> GetPlayerNameHashedAsync()
public string GetPlayerNameHashed()
{
return await RunOnFrameworkThread(() => _cid.Value.ToString().GetHash256()).ConfigureAwait(false);
return _cid.Value.ToString().GetHash256();
}
public static unsafe bool TryGetHashedCID(IPlayerCharacter? playerCharacter, out string hashedCid)
@@ -653,54 +648,100 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
public uint GetHomeWorldId()
{
EnsureIsOnFramework();
return _objectTable.LocalPlayer?.HomeWorld.RowId ?? 0;
return _playerState.HomeWorld.RowId;
}
public uint GetWorldId()
{
EnsureIsOnFramework();
return _objectTable.LocalPlayer!.CurrentWorld.RowId;
return _playerState.CurrentWorld.RowId;
}
public unsafe LocationInfo GetMapData()
{
EnsureIsOnFramework();
var agentMap = AgentMap.Instance();
var houseMan = HousingManager.Instance();
uint serverId = 0;
if (_objectTable.LocalPlayer == null) serverId = 0;
else serverId = _objectTable.LocalPlayer.CurrentWorld.RowId;
uint mapId = agentMap == null ? 0 : agentMap->CurrentMapId;
uint territoryId = agentMap == null ? 0 : agentMap->CurrentTerritoryId;
uint divisionId = houseMan == null ? 0 : (uint)(houseMan->GetCurrentDivision());
uint wardId = houseMan == null ? 0 : (uint)(houseMan->GetCurrentWard() + 1);
uint houseId = 0;
var tempHouseId = houseMan == null ? 0 : (houseMan->GetCurrentPlot());
if (!houseMan->IsInside()) tempHouseId = 0;
if (tempHouseId < -1)
{
divisionId = tempHouseId == -127 ? 2 : (uint)1;
tempHouseId = 100;
}
if (tempHouseId == -1) tempHouseId = 0;
houseId = (uint)tempHouseId;
if (houseId != 0)
{
territoryId = HousingManager.GetOriginalHouseTerritoryTypeId();
}
uint roomId = houseMan == null ? 0 : (uint)(houseMan->GetCurrentRoom());
return new LocationInfo()
var location = new LocationInfo();
location.ServerId = _playerState.CurrentWorld.RowId;
location.InstanceId = UIState.Instance()->PublicInstance.InstanceId;
location.TerritoryId = _clientState.TerritoryType;
location.MapId = _clientState.MapId;
if (houseMan != null)
{
ServerId = serverId,
MapId = mapId,
TerritoryId = territoryId,
DivisionId = divisionId,
WardId = wardId,
HouseId = houseId,
RoomId = roomId
};
if (houseMan->IsInside())
{
location.TerritoryId = HousingManager.GetOriginalHouseTerritoryTypeId();
var house = houseMan->GetCurrentIndoorHouseId();
location.WardId = house.WardIndex + 1u;
location.HouseId = house.IsApartment ? 100 : house.PlotIndex + 1u;
location.RoomId = (uint)house.RoomNumber;
location.DivisionId = house.IsApartment ? house.ApartmentDivision + 1u : houseMan->GetCurrentDivision();
}
else if (houseMan->IsInWorkshop())
{
var workShop = houseMan->WorkshopTerritory;
var house = workShop->HouseId;
location.WardId = house.WardIndex + 1u;
location.HouseId = house.PlotIndex + 1u;
}
else if (houseMan->IsOutside())
{
var outside = houseMan->OutdoorTerritory;
var house = outside->HouseId;
location.WardId = house.WardIndex + 1u;
location.HouseId = (uint)houseMan->GetCurrentPlot() + 1;
location.DivisionId = houseMan->GetCurrentDivision();
}
//_logger.LogWarning(LocationToString(location));
}
return location;
}
public string LocationToString(LocationInfo location)
{
if (location.ServerId is 0 || location.TerritoryId is 0) return String.Empty;
var str = WorldData.Value[(ushort)location.ServerId];
if (ContentFinderData.Value.TryGetValue(location.TerritoryId , out var dutyName))
{
str += $" - [In Duty]{dutyName}";
}
else
{
if (location.HouseId is not 0 || location.MapId is 0) // Dont show mapName when in house/no map available
{
str += $" - {TerritoryData.Value[(ushort)location.TerritoryId]}";
}
else
{
str += $" - {MapData.Value[(ushort)location.MapId].MapName}";
}
if (location.InstanceId is not 0)
{
str += ((SeIconChar)(57520 + location.InstanceId)).ToIconString();
}
if (location.WardId is not 0)
{
str += $" Ward #{location.WardId}";
}
if (location.HouseId is not 0 and not 100)
{
str += $" House #{location.HouseId}";
}
else if (location.HouseId is 100)
{
str += $" {(location.DivisionId == 2 ? "[Subdivision]" : "")} Apartment";
}
if (location.RoomId is not 0)
{
str += $" Room #{location.RoomId}";
}
}
return str;
}
public unsafe void SetMarkerAndOpenMap(Vector3 position, Map map)
@@ -712,21 +753,6 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
agentMap->SetFlagMapMarker(map.TerritoryType.RowId, map.RowId, position);
}
public async Task<LocationInfo> GetMapDataAsync()
{
return await RunOnFrameworkThread(GetMapData).ConfigureAwait(false);
}
public async Task<uint> GetWorldIdAsync()
{
return await RunOnFrameworkThread(GetWorldId).ConfigureAwait(false);
}
public async Task<uint> GetHomeWorldIdAsync()
{
return await RunOnFrameworkThread(GetHomeWorldId).ConfigureAwait(false);
}
public unsafe bool IsGameObjectPresent(IntPtr key)
{
return _objectTable.Any(f => f.Address == key);

View File

@@ -67,7 +67,7 @@ public class LightFinderService : IHostedService, IMediatorSubscriber
{
try
{
var cid = await _dalamudUtil.GetCIDAsync().ConfigureAwait(false);
var cid = _dalamudUtil.GetCID();
return cid.ToString().GetHash256();
}
catch (Exception ex)

View File

@@ -0,0 +1,78 @@
using LightlessSync.API.Data;
using LightlessSync.API.Dto.CharaData;
using LightlessSync.API.Dto.User;
using LightlessSync.Services.Mediator;
using LightlessSync.WebAPI;
using Microsoft.Extensions.Logging;
namespace LightlessSync.Services
{
public class LocationShareService : DisposableMediatorSubscriberBase
{
private readonly DalamudUtilService _dalamudUtilService;
private readonly ApiController _apiController;
private Dictionary<string, LocationInfo> _locations = [];
public LocationShareService(ILogger<LocationShareService> logger, LightlessMediator mediator, DalamudUtilService dalamudUtilService, ApiController apiController) : base(logger, mediator)
{
_dalamudUtilService = dalamudUtilService;
_apiController = apiController;
Mediator.Subscribe<DisconnectedMessage>(this, (msg) => _locations.Clear());
Mediator.Subscribe<ConnectedMessage>(this, (msg) =>
{
_ = _apiController.UpdateLocation(new LocationDto(new UserData(_apiController.UID, apiController.DisplayName), _dalamudUtilService.GetMapData()));
_ = RequestAllLocation();
} );
Mediator.Subscribe<LocationMessage>(this, UpdateLocationList);
Mediator.Subscribe<ZoneSwitchEndMessage>(this,
msg => _ = _apiController.UpdateLocation(new LocationDto(new UserData(_apiController.UID, _apiController.DisplayName), _dalamudUtilService.GetMapData())));
}
private void UpdateLocationList(LocationMessage msg)
{
if (_locations.ContainsKey(msg.Uid) && msg.LocationInfo.ServerId is 0)
{
_locations.Remove(msg.Uid);
return;
}
if ( msg.LocationInfo.ServerId is not 0 && !_locations.TryAdd(msg.Uid, msg.LocationInfo))
{
_locations[msg.Uid] = msg.LocationInfo;
}
}
private async Task RequestAllLocation()
{
try
{
var data = await _apiController.RequestAllLocationInfo().ConfigureAwait(false);
_locations = data.ToDictionary(x => x.user.UID, x => x.location, StringComparer.Ordinal);
}
catch (Exception e)
{
Logger.LogError(e,"RequestAllLocation error : ");
throw;
}
}
public string GetUserLocation(string uid)
{
try
{
if (_locations.TryGetValue(uid, out var location))
{
return _dalamudUtilService.LocationToString(location);
}
return String.Empty;
}
catch (Exception e)
{
Logger.LogError(e,"GetUserLocation error : ");
throw;
}
}
}
}

View File

@@ -135,5 +135,7 @@ public record ChatChannelsUpdated : MessageBase;
public record ChatChannelMessageAdded(string ChannelKey, ChatMessageEntry Message) : MessageBase;
public record GroupCollectionChangedMessage : MessageBase;
public record OpenUserProfileMessage(UserData User) : MessageBase;
public record LocationMessage(string Uid, LocationInfo LocationInfo) : MessageBase;
#pragma warning restore S2094
#pragma warning restore MA0048 // File name must match type name

View File

@@ -101,9 +101,9 @@ public class ServerConfigurationManager
}
hasMulti = false;
var charaName = _dalamudUtil.GetPlayerNameAsync().GetAwaiter().GetResult();
var worldId = _dalamudUtil.GetHomeWorldIdAsync().GetAwaiter().GetResult();
var cid = _dalamudUtil.GetCIDAsync().GetAwaiter().GetResult();
var charaName = _dalamudUtil.GetPlayerName();
var worldId = _dalamudUtil.GetHomeWorldId();
var cid = _dalamudUtil.GetCID();
var auth = currentServer.Authentications.FindAll(f => string.Equals(f.CharacterName, charaName) && f.WorldId == worldId);
if (auth.Count >= 2)
@@ -148,9 +148,9 @@ public class ServerConfigurationManager
}
hasMulti = false;
var charaName = _dalamudUtil.GetPlayerNameAsync().GetAwaiter().GetResult();
var worldId = _dalamudUtil.GetHomeWorldIdAsync().GetAwaiter().GetResult();
var cid = _dalamudUtil.GetCIDAsync().GetAwaiter().GetResult();
var charaName = _dalamudUtil.GetPlayerName();
var worldId = _dalamudUtil.GetHomeWorldId();
var cid = _dalamudUtil.GetCID();
if (!currentServer.Authentications.Any() && currentServer.SecretKeys.Any())
{
currentServer.Authentications.Add(new Authentication()
@@ -268,16 +268,16 @@ public class ServerConfigurationManager
{
if (serverSelectionIndex == -1) serverSelectionIndex = CurrentServerIndex;
var server = GetServerByIndex(serverSelectionIndex);
if (server.Authentications.Exists(c => string.Equals(c.CharacterName, _dalamudUtil.GetPlayerNameAsync().GetAwaiter().GetResult(), StringComparison.Ordinal)
&& c.WorldId == _dalamudUtil.GetHomeWorldIdAsync().GetAwaiter().GetResult()))
if (server.Authentications.Exists(c => string.Equals(c.CharacterName, _dalamudUtil.GetPlayerName(), StringComparison.Ordinal)
&& c.WorldId == _dalamudUtil.GetHomeWorldId()))
return;
server.Authentications.Add(new Authentication()
{
CharacterName = _dalamudUtil.GetPlayerNameAsync().GetAwaiter().GetResult(),
WorldId = _dalamudUtil.GetHomeWorldIdAsync().GetAwaiter().GetResult(),
CharacterName = _dalamudUtil.GetPlayerName(),
WorldId = _dalamudUtil.GetHomeWorldId(),
SecretKeyIdx = !server.UseOAuth2 ? server.SecretKeys.Last().Key : -1,
LastSeenCID = _dalamudUtil.GetCIDAsync().GetAwaiter().GetResult()
LastSeenCID = _dalamudUtil.GetCID()
});
Save();
}

View File

@@ -131,6 +131,7 @@ public class DrawFolderGroup : DrawFolderBase
bool disableSounds = perm.IsDisableSounds();
bool disableAnims = perm.IsDisableAnimations();
bool disableVfx = perm.IsDisableVFX();
bool shareLocation = perm.IsSharingLocation();
if ((_groupFullInfoDto.GroupPermissions.IsPreferDisableAnimations() != disableAnims
|| _groupFullInfoDto.GroupPermissions.IsPreferDisableSounds() != disableSounds
@@ -164,6 +165,13 @@ public class DrawFolderGroup : DrawFolderBase
_ = _apiController.GroupChangeIndividualPermissionState(new(_groupFullInfoDto.Group, new(_apiController.UID), perm));
ImGui.CloseCurrentPopup();
}
if (_uiSharedService.IconTextButton(!shareLocation ? FontAwesomeIcon.Globe : FontAwesomeIcon.StopCircle, !shareLocation ? "Share your location to all users in Syncshell" : "STOP Share your location to all users in Syncshell", menuWidth, true))
{
perm.SetShareLocation(!shareLocation);
_ = _apiController.GroupChangeIndividualPermissionState(new(_groupFullInfoDto.Group, new(_apiController.UID), perm));
ImGui.CloseCurrentPopup();
}
if (IsModerator || IsOwner)
{

View File

@@ -37,6 +37,7 @@ public class DrawUserPair
private readonly UiSharedService _uiSharedService;
private readonly PlayerPerformanceConfigService _performanceConfigService;
private readonly LightlessConfigService _configService;
private readonly LocationShareService _locationShareService;
private readonly CharaDataManager _charaDataManager;
private readonly PairLedger _pairLedger;
private float _menuWidth = -1;
@@ -57,6 +58,7 @@ public class DrawUserPair
UiSharedService uiSharedService,
PlayerPerformanceConfigService performanceConfigService,
LightlessConfigService configService,
LocationShareService locationShareService,
CharaDataManager charaDataManager,
PairLedger pairLedger)
{
@@ -74,6 +76,7 @@ public class DrawUserPair
_uiSharedService = uiSharedService;
_performanceConfigService = performanceConfigService;
_configService = configService;
_locationShareService = locationShareService;
_charaDataManager = charaDataManager;
_pairLedger = pairLedger;
}
@@ -216,6 +219,17 @@ public class DrawUserPair
_ = _apiController.UserSetPairPermissions(new UserPermissionsDto(_pair.UserData, permissions));
}
UiSharedService.AttachToolTip("Changes VFX sync permissions with this user." + (individual ? individualText : string.Empty));
var isShareingLocation = _pair.UserPair!.OwnPermissions.IsSharingLocation();
string isShareingLocationText = isShareingLocation ? "Disable location sharing" : "Enable location sharing";
var isShareingLocationIcon = isShareingLocation ? FontAwesomeIcon.StopCircle : FontAwesomeIcon.Globe;
if (_uiSharedService.IconTextButton(isShareingLocationIcon, isShareingLocationText, _menuWidth, true))
{
var permissions = _pair.UserPair.OwnPermissions;
permissions.SetShareLocation(!isShareingLocation);
_ = _apiController.UserSetPairPermissions(new UserPermissionsDto(_pair.UserData, permissions));
}
UiSharedService.AttachToolTip("Changes location sharing permissions with this user." + (individual ? individualText : string.Empty));
}
private void DrawIndividualMenu()
@@ -567,6 +581,7 @@ public class DrawUserPair
: UiSharedService.TooltipSeparator + "Hold CTRL to enable preferred permissions while pausing." + Environment.NewLine + "This will leave this pair paused even if unpausing syncshells including this pair."))
: "Resume pairing with " + _pair.UserData.AliasOrUID);
//Location sharing
if (_pair.IsPaired)
{
var individualSoundsDisabled = (_pair.UserPair?.OwnPermissions.IsDisableSounds() ?? false) || (_pair.UserPair?.OtherPermissions.IsDisableSounds() ?? false);
@@ -574,6 +589,66 @@ public class DrawUserPair
var individualVFXDisabled = (_pair.UserPair?.OwnPermissions.IsDisableVFX() ?? false) || (_pair.UserPair?.OtherPermissions.IsDisableVFX() ?? false);
var individualIsSticky = _pair.UserPair!.OwnPermissions.IsSticky();
var individualIcon = individualIsSticky ? FontAwesomeIcon.ArrowCircleUp : FontAwesomeIcon.InfoCircle;
var shareLocationIcon = FontAwesomeIcon.Globe;
var shareLocation = _pair.UserPair?.OwnPermissions.IsSharingLocation() ?? false;
var shareLocationOther = _pair.UserPair?.OtherPermissions.IsSharingLocation() ?? false;
var shareColor = shareLocation switch
{
true when shareLocationOther => UIColors.Get("LightlessGreen"),
false when shareLocationOther => UIColors.Get("LightlessBlue"),
_ => UIColors.Get("LightlessYellow"),
};
if (shareLocation || shareLocationOther)
{
currentRightSide -= (_uiSharedService.GetIconSize(shareLocationIcon).X + spacingX);
ImGui.SameLine(currentRightSide);
using (ImRaii.PushColor(ImGuiCol.Text, shareColor, shareLocation || shareLocationOther))
_uiSharedService.IconText(shareLocationIcon);
if (ImGui.IsItemHovered())
{
ImGui.BeginTooltip();
if (shareLocationOther)
{
var location = _locationShareService.GetUserLocation(_pair.UserPair!.User.UID);
if (_pair.IsOnline)
{
if (!string.IsNullOrEmpty(location))
{
_uiSharedService.IconText(FontAwesomeIcon.LocationArrow);
ImGui.SameLine();
ImGui.TextUnformatted(location);
}
else
{
ImGui.TextUnformatted("Location info not updated, reconnect or waiting for zone-changing.");
}
}
else
{
ImGui.TextUnformatted("User not onlineㄟ( ▔, ▔ )ㄏ");
}
}
else
{
ImGui.TextUnformatted("NOT Sharing location with you.(⊙x⊙;)");
}
ImGui.Separator();
if (shareLocation)
{
ImGui.TextUnformatted("Sharing your location.ヾ(•ω•`)o");
}
else
{
ImGui.TextUnformatted("NOT sharing your location.(´。_。`)");
}
ImGui.EndTooltip();
}
}
if (individualAnimDisabled || individualSoundsDisabled || individualVFXDisabled || individualIsSticky)
{

View File

@@ -28,6 +28,7 @@ public class DrawEntityFactory
private readonly ServerConfigurationManager _serverConfigurationManager;
private readonly LightlessConfigService _configService;
private readonly UiSharedService _uiSharedService;
private readonly LocationShareService _locationShareService;
private readonly PlayerPerformanceConfigService _playerPerformanceConfigService;
private readonly CharaDataManager _charaDataManager;
private readonly SelectTagForPairUi _selectTagForPairUi;
@@ -52,6 +53,7 @@ public class DrawEntityFactory
ServerConfigurationManager serverConfigurationManager,
LightlessConfigService configService,
UiSharedService uiSharedService,
LocationShareService locationShareService,
PlayerPerformanceConfigService playerPerformanceConfigService,
CharaDataManager charaDataManager,
SelectTagForSyncshellUi selectTagForSyncshellUi,
@@ -71,6 +73,7 @@ public class DrawEntityFactory
_serverConfigurationManager = serverConfigurationManager;
_configService = configService;
_uiSharedService = uiSharedService;
_locationShareService = locationShareService;
_playerPerformanceConfigService = playerPerformanceConfigService;
_charaDataManager = charaDataManager;
_selectTagForSyncshellUi = selectTagForSyncshellUi;
@@ -162,6 +165,7 @@ public class DrawEntityFactory
_uiSharedService,
_playerPerformanceConfigService,
_configService,
_locationShareService,
_charaDataManager,
_pairLedger);
}

View File

@@ -364,28 +364,21 @@ public sealed class DtrEntry : IDisposable, IHostedService
return;
}
_ = Task.Run(async () =>
try
{
try
var cid = _dalamudUtilService.GetCID();
var hashedCid = cid.ToString().GetHash256();
_localHashedCid = hashedCid;
_localHashedCidFetchedAt = now;
return hashedCid;
}
catch (Exception ex)
{
if (now >= _localHashedCidNextErrorLog)
{
var cid = await _dalamudUtilService.GetCIDAsync().ConfigureAwait(false);
var hashedCid = cid.ToString().GetHash256();
lock (_localHashedCidLock)
{
_localHashedCid = hashedCid;
_localHashedCidFetchedAt = DateTime.UtcNow;
}
_logger.LogDebug(ex, "Failed to refresh local hashed CID for Lightfinder DTR entry.");
_localHashedCidNextErrorLog = now + _localHashedCidErrorCooldown;
}
catch (Exception ex)
{
var now = DateTime.UtcNow;
lock (_localHashedCidLock)
{
if (now >= _localHashedCidNextErrorLog)
{
_logger.LogDebug(ex, "Failed to refresh local hashed CID for Lightfinder DTR entry.");
_localHashedCidNextErrorLog = now + _localHashedCidErrorCooldown;
}
_localHashedCid = null;
_localHashedCidFetchedAt = now;

View File

@@ -43,6 +43,7 @@ public class PermissionWindowUI : WindowMediatorSubscriberBase
var disableSounds = _ownPermissions.IsDisableSounds();
var disableAnimations = _ownPermissions.IsDisableAnimations();
var disableVfx = _ownPermissions.IsDisableVFX();
var shareLocation = _ownPermissions.IsSharingLocation();
var style = ImGui.GetStyle();
var indentSize = ImGui.GetFrameHeight() + style.ItemSpacing.X;
@@ -70,6 +71,7 @@ public class PermissionWindowUI : WindowMediatorSubscriberBase
var otherDisableSounds = otherPerms.IsDisableSounds();
var otherDisableAnimations = otherPerms.IsDisableAnimations();
var otherDisableVFX = otherPerms.IsDisableVFX();
var otherShareLocation = otherPerms.IsSharingLocation();
using (ImRaii.PushIndent(indentSize, false))
{
@@ -124,6 +126,24 @@ public class PermissionWindowUI : WindowMediatorSubscriberBase
ImGui.AlignTextToFramePadding();
ImGui.Text(Pair.UserData.AliasOrUID + " has " + (!otherDisableVFX ? "not " : string.Empty) + "disabled VFX sync with you");
}
if (ImGui.Checkbox("Enable location Sharing", ref shareLocation))
{
_ownPermissions.SetShareLocation(shareLocation);
}
_uiSharedService.DrawHelpText("Enable location sharing will only effect your side." + UiSharedService.TooltipSeparator
+ "Note: this is NOT bidirectional, you can choose to share even others dont share with you.");
using (ImRaii.PushIndent(indentSize, false))
{
_uiSharedService.BooleanToColoredIcon(shareLocation, false);
ImGui.SameLine();
ImGui.AlignTextToFramePadding();
ImGui.Text((!shareLocation ? "Not" : string.Empty) + "sharing location with " + Pair.UserData.AliasOrUID + " .");
#if DEBUG
_uiSharedService.BooleanToColoredIcon(otherShareLocation, true);
#endif
}
ImGuiHelpers.ScaledDummy(0.5f);
ImGui.Separator();

View File

@@ -431,7 +431,7 @@ public class TopTabMenu
try
{
var myCidHash = (await _dalamudUtilService.GetCIDAsync().ConfigureAwait(false)).ToString().GetHash256();
var myCidHash = _dalamudUtilService.GetCID().ToString().GetHash256();
await _apiController.TryPairWithContentId(request.HashedCid).ConfigureAwait(false);
_pairRequestService.RemoveRequest(request.HashedCid);

View File

@@ -193,12 +193,24 @@ public partial class ApiController
CensusDataDto? censusDto = null;
if (_serverManager.SendCensusData && _lastCensus != null)
{
var world = await _dalamudUtil.GetWorldIdAsync().ConfigureAwait(false);
var world = _dalamudUtil.GetWorldId();
censusDto = new((ushort)world, _lastCensus.RaceId, _lastCensus.TribeId, _lastCensus.Gender);
Logger.LogDebug("Attaching Census Data: {data}", censusDto);
}
await UserPushData(new(visibleCharacters, character, censusDto)).ConfigureAwait(false);
}
public async Task UpdateLocation(LocationDto locationDto, bool offline = false)
{
if (!IsConnected) return;
await _lightlessHub!.SendAsync(nameof(UpdateLocation), locationDto, offline).ConfigureAwait(false);
}
public async Task<List<LocationDto>> RequestAllLocationInfo()
{
if (!IsConnected) return [];
return await _lightlessHub!.InvokeAsync<List<LocationDto>>(nameof(RequestAllLocationInfo)).ConfigureAwait(false);
}
}
#pragma warning restore MA0040

View File

@@ -259,6 +259,13 @@ public partial class ApiController
ExecuteSafely(() => Mediator.Publish(new GPoseLobbyReceiveWorldData(userData, worldData)));
return Task.CompletedTask;
}
public Task Client_SendLocationToClient(LocationDto locationDto)
{
Logger.LogDebug($"{nameof(Client_SendLocationToClient)}: {locationDto.user}");
ExecuteSafely(() => Mediator.Publish(new LocationMessage(locationDto.user.UID, locationDto.location)));
return Task.CompletedTask;
}
public void OnDownloadReady(Action<Guid> act)
{
@@ -440,6 +447,12 @@ public partial class ApiController
if (_initialized) return;
_lightlessHub!.On(nameof(Client_GposeLobbyPushWorldData), act);
}
public void OnReciveLocation(Action<LocationDto> act)
{
if (_initialized) return;
_lightlessHub!.On(nameof(Client_SendLocationToClient), act);
}
private void ExecuteSafely(Action act)
{

View File

@@ -544,8 +544,8 @@ public sealed partial class ApiController : DisposableMediatorSubscriberBase, IL
private void DalamudUtilOnLogIn()
{
var charaName = _dalamudUtil.GetPlayerNameAsync().GetAwaiter().GetResult();
var worldId = _dalamudUtil.GetHomeWorldIdAsync().GetAwaiter().GetResult();
var charaName = _dalamudUtil.GetPlayerName();
var worldId = _dalamudUtil.GetHomeWorldId();
var auth = _serverManager.CurrentServer.Authentications.Find(f => string.Equals(f.CharacterName, charaName, StringComparison.Ordinal) && f.WorldId == worldId);
if (auth?.AutoLogin ?? false)
{
@@ -606,6 +606,8 @@ public sealed partial class ApiController : DisposableMediatorSubscriberBase, IL
OnGposeLobbyPushCharacterData((dto) => _ = Client_GposeLobbyPushCharacterData(dto));
OnGposeLobbyPushPoseData((dto, data) => _ = Client_GposeLobbyPushPoseData(dto, data));
OnGposeLobbyPushWorldData((dto, data) => _ = Client_GposeLobbyPushWorldData(dto, data));
OnReciveLocation(dto => _ = Client_SendLocationToClient(dto));
_healthCheckTokenSource?.Cancel();
_healthCheckTokenSource?.Dispose();
@@ -653,7 +655,7 @@ public sealed partial class ApiController : DisposableMediatorSubscriberBase, IL
CensusDataDto? dto = null;
if (_serverManager.SendCensusData && _lastCensus != null)
{
var world = await _dalamudUtil.GetWorldIdAsync().ConfigureAwait(false);
var world = _dalamudUtil.GetWorldId();
dto = new((ushort)world, _lastCensus.RaceId, _lastCensus.TribeId, _lastCensus.Gender);
Logger.LogDebug("Attaching Census Data: {data}", dto);
}

View File

@@ -72,7 +72,7 @@ public sealed class TokenProvider : IDisposable, IMediatorSubscriber
result = await _httpClient.PostAsync(tokenUri, new FormUrlEncodedContent(
[
new KeyValuePair<string, string>("auth", auth),
new KeyValuePair<string, string>("charaIdent", await _dalamudUtil.GetPlayerNameHashedAsync().ConfigureAwait(false)),
new KeyValuePair<string, string>("charaIdent", _dalamudUtil.GetPlayerNameHashed()),
]), ct).ConfigureAwait(false);
}
else
@@ -152,7 +152,7 @@ public sealed class TokenProvider : IDisposable, IMediatorSubscriber
JwtIdentifier jwtIdentifier;
try
{
var playerIdentifier = await _dalamudUtil.GetPlayerNameHashedAsync().ConfigureAwait(false);
var playerIdentifier = _dalamudUtil.GetPlayerNameHashed();
if (string.IsNullOrEmpty(playerIdentifier))
{