adjust visibility flags, improve chat functionality, bump submodules
This commit is contained in:
@@ -783,7 +783,7 @@ public sealed class ActorObjectService : IHostedService, IDisposable
|
||||
if (drawObject == null)
|
||||
return false;
|
||||
|
||||
if ((ushort)gameObject->RenderFlags == 2048)
|
||||
if ((gameObject->RenderFlags & VisibilityFlags.Nameplate) != VisibilityFlags.None)
|
||||
return false;
|
||||
|
||||
var characterBase = (CharacterBase*)drawObject;
|
||||
|
||||
@@ -3,10 +3,21 @@ using LightlessSync.API.Dto.Chat;
|
||||
namespace LightlessSync.Services.Chat;
|
||||
|
||||
public sealed record ChatMessageEntry(
|
||||
ChatMessageDto Payload,
|
||||
ChatMessageDto? Payload,
|
||||
string DisplayName,
|
||||
bool FromSelf,
|
||||
DateTime ReceivedAtUtc);
|
||||
DateTime ReceivedAtUtc,
|
||||
ChatSystemEntry? SystemMessage = null)
|
||||
{
|
||||
public bool IsSystem => SystemMessage is not null;
|
||||
}
|
||||
|
||||
public enum ChatSystemEntryType
|
||||
{
|
||||
ZoneSeparator
|
||||
}
|
||||
|
||||
public sealed record ChatSystemEntry(ChatSystemEntryType Type, string? ZoneName);
|
||||
|
||||
public readonly record struct ChatChannelSnapshot(
|
||||
string Key,
|
||||
|
||||
@@ -240,8 +240,22 @@ public sealed class ZoneChatService : DisposableMediatorSubscriberBase, IHostedS
|
||||
}
|
||||
}
|
||||
|
||||
public Task<ChatParticipantResolveResultDto?> ResolveParticipantAsync(ChatChannelDescriptor descriptor, string token)
|
||||
=> _apiController.ResolveChatParticipant(new ChatParticipantResolveRequestDto(descriptor, token));
|
||||
public async Task<bool> SetParticipantMuteAsync(ChatChannelDescriptor descriptor, string token, bool mute)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(token))
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
await _apiController.SetChatParticipantMute(new ChatParticipantMuteRequestDto(descriptor, token, mute)).ConfigureAwait(false);
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogWarning(ex, "Failed to update chat participant mute state");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public Task<ChatReportResult> ReportMessageAsync(ChatChannelDescriptor descriptor, string messageId, string reason, string? additionalContext)
|
||||
{
|
||||
@@ -534,6 +548,7 @@ public sealed class ZoneChatService : DisposableMediatorSubscriberBase, IHostedS
|
||||
}
|
||||
|
||||
bool shouldForceSend;
|
||||
ChatMessageEntry? zoneSeparatorEntry = null;
|
||||
|
||||
using (_sync.EnterScope())
|
||||
{
|
||||
@@ -544,11 +559,24 @@ public sealed class ZoneChatService : DisposableMediatorSubscriberBase, IHostedS
|
||||
state.IsAvailable = _chatEnabled;
|
||||
state.StatusText = _chatEnabled ? null : "Chat services disabled";
|
||||
|
||||
var previousDescriptor = _lastZoneDescriptor;
|
||||
var zoneChanged = previousDescriptor.HasValue && !ChannelDescriptorsMatch(previousDescriptor.Value, descriptor.Value);
|
||||
|
||||
_activeChannelKey = ZoneChannelKey;
|
||||
shouldForceSend = force || !_lastZoneDescriptor.HasValue || !ChannelDescriptorsMatch(_lastZoneDescriptor.Value, descriptor.Value);
|
||||
shouldForceSend = force || !previousDescriptor.HasValue || zoneChanged;
|
||||
if (zoneChanged && state.Messages.Any(m => !m.IsSystem))
|
||||
{
|
||||
zoneSeparatorEntry = AddZoneSeparatorLocked(state, definition.Value.DisplayName);
|
||||
}
|
||||
|
||||
_lastZoneDescriptor = descriptor;
|
||||
}
|
||||
|
||||
if (zoneSeparatorEntry is not null)
|
||||
{
|
||||
Mediator.Publish(new ChatChannelMessageAdded(ZoneChannelKey, zoneSeparatorEntry));
|
||||
}
|
||||
|
||||
PublishChannelListChanged();
|
||||
await SendPresenceAsync(descriptor.Value, territoryId, isActive: true, force: shouldForceSend).ConfigureAwait(false);
|
||||
}
|
||||
@@ -561,7 +589,6 @@ public sealed class ZoneChatService : DisposableMediatorSubscriberBase, IHostedS
|
||||
private async Task LeaveCurrentZoneAsync(bool force, ushort territoryId)
|
||||
{
|
||||
ChatChannelDescriptor? descriptor = null;
|
||||
bool clearedHistory = false;
|
||||
|
||||
using (_sync.EnterScope())
|
||||
{
|
||||
@@ -570,15 +597,6 @@ public sealed class ZoneChatService : DisposableMediatorSubscriberBase, IHostedS
|
||||
|
||||
if (_channels.TryGetValue(ZoneChannelKey, out var state))
|
||||
{
|
||||
if (state.Messages.Count > 0)
|
||||
{
|
||||
state.Messages.Clear();
|
||||
state.HasUnread = false;
|
||||
state.UnreadCount = 0;
|
||||
_lastReadCounts[ZoneChannelKey] = 0;
|
||||
clearedHistory = true;
|
||||
}
|
||||
|
||||
state.IsConnected = _isConnected;
|
||||
state.IsAvailable = false;
|
||||
state.StatusText = !_chatEnabled
|
||||
@@ -593,11 +611,6 @@ public sealed class ZoneChatService : DisposableMediatorSubscriberBase, IHostedS
|
||||
}
|
||||
}
|
||||
|
||||
if (clearedHistory)
|
||||
{
|
||||
PublishHistoryCleared(ZoneChannelKey);
|
||||
}
|
||||
|
||||
PublishChannelListChanged();
|
||||
|
||||
if (descriptor.HasValue)
|
||||
@@ -1007,6 +1020,39 @@ public sealed class ZoneChatService : DisposableMediatorSubscriberBase, IHostedS
|
||||
return new ChatMessageEntry(dto, displayName, fromSelf, DateTime.UtcNow);
|
||||
}
|
||||
|
||||
private ChatMessageEntry AddZoneSeparatorLocked(ChatChannelState state, string zoneDisplayName)
|
||||
{
|
||||
var separator = new ChatMessageEntry(
|
||||
null,
|
||||
string.Empty,
|
||||
false,
|
||||
DateTime.UtcNow,
|
||||
new ChatSystemEntry(ChatSystemEntryType.ZoneSeparator, zoneDisplayName));
|
||||
|
||||
state.Messages.Add(separator);
|
||||
if (state.Messages.Count > MaxMessageHistory)
|
||||
{
|
||||
state.Messages.RemoveAt(0);
|
||||
}
|
||||
|
||||
if (string.Equals(_activeChannelKey, ZoneChannelKey, StringComparison.Ordinal))
|
||||
{
|
||||
state.HasUnread = false;
|
||||
state.UnreadCount = 0;
|
||||
_lastReadCounts[ZoneChannelKey] = state.Messages.Count;
|
||||
}
|
||||
else if (_lastReadCounts.TryGetValue(ZoneChannelKey, out var readCount))
|
||||
{
|
||||
_lastReadCounts[ZoneChannelKey] = readCount + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
_lastReadCounts[ZoneChannelKey] = state.Messages.Count;
|
||||
}
|
||||
|
||||
return separator;
|
||||
}
|
||||
|
||||
private string ResolveDisplayName(ChatMessageDto dto, bool fromSelf)
|
||||
{
|
||||
var isZone = dto.Channel.Type == ChatChannelType.Zone;
|
||||
@@ -1070,8 +1116,6 @@ public sealed class ZoneChatService : DisposableMediatorSubscriberBase, IHostedS
|
||||
|
||||
private void PublishChannelListChanged() => Mediator.Publish(new ChatChannelsUpdated());
|
||||
|
||||
private void PublishHistoryCleared(string channelKey) => Mediator.Publish(new ChatChannelHistoryCleared(channelKey));
|
||||
|
||||
private static IEnumerable<string> EnumerateTerritoryKeys(string? value)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
|
||||
@@ -26,6 +26,7 @@ using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using DalamudObjectKind = Dalamud.Game.ClientState.Objects.Enums.ObjectKind;
|
||||
using GameObject = FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject;
|
||||
using VisibilityFlags = FFXIVClientStructs.FFXIV.Client.Game.Object.VisibilityFlags;
|
||||
|
||||
namespace LightlessSync.Services;
|
||||
|
||||
@@ -707,7 +708,7 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
|
||||
const int tick = 250;
|
||||
int curWaitTime = 0;
|
||||
_logger.LogTrace("RenderFlags: {flags}", obj->RenderFlags.ToString("X"));
|
||||
while (obj->RenderFlags != 0x00 && curWaitTime < timeOut)
|
||||
while (obj->RenderFlags != VisibilityFlags.None && curWaitTime < timeOut)
|
||||
{
|
||||
_logger.LogTrace($"Waiting for gpose actor to finish drawing");
|
||||
curWaitTime += tick;
|
||||
@@ -752,7 +753,7 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
|
||||
bool isDrawingChanged = false;
|
||||
if ((nint)drawObj != IntPtr.Zero)
|
||||
{
|
||||
isDrawing = (ushort)gameObj->RenderFlags == 0b100000000000;
|
||||
isDrawing = (gameObj->RenderFlags & VisibilityFlags.Nameplate) != VisibilityFlags.None;
|
||||
if (!isDrawing)
|
||||
{
|
||||
isDrawing = ((CharacterBase*)drawObj)->HasModelInSlotLoaded != 0;
|
||||
|
||||
@@ -133,7 +133,6 @@ public record PairDownloadStatusMessage(List<(string PlayerName, float Progress,
|
||||
public record VisibilityChange : MessageBase;
|
||||
public record ChatChannelsUpdated : MessageBase;
|
||||
public record ChatChannelMessageAdded(string ChannelKey, ChatMessageEntry Message) : MessageBase;
|
||||
public record ChatChannelHistoryCleared(string ChannelKey) : MessageBase;
|
||||
public record GroupCollectionChangedMessage : MessageBase;
|
||||
public record OpenUserProfileMessage(UserData User) : MessageBase;
|
||||
#pragma warning restore S2094
|
||||
|
||||
@@ -327,7 +327,12 @@ public class LightlessProfileManager : MediatorSubscriberBase
|
||||
if (profile == null)
|
||||
return null;
|
||||
|
||||
var userData = profile.User;
|
||||
if (profile.User is null)
|
||||
{
|
||||
Logger.LogWarning("Lightfinder profile response missing user info for CID {HashedCid}", hashedCid);
|
||||
}
|
||||
|
||||
var userData = profile.User ?? new UserData(hashedCid, Alias: "Lightfinder User");
|
||||
var profileTags = profile.Tags ?? _emptyTagSet;
|
||||
var profileData = BuildProfileData(userData, profile, profileTags);
|
||||
_lightlessProfiles[userData] = profileData;
|
||||
|
||||
Reference in New Issue
Block a user