Merge remote-tracking branch 'origin/2.0.2-Location' into 2.0.0-crashing-bugfixes

# Conflicts:
#	LightlessSync/UI/DtrEntry.cs
This commit is contained in:
choco
2025-12-27 23:13:20 +01:00
24 changed files with 362 additions and 124 deletions

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();
}