From e1f23d6758ea3ec855c80caaa06dcdea239d3ae7 Mon Sep 17 00:00:00 2001 From: sleepyyapril Date: Sat, 8 Nov 2025 14:10:54 -0400 Subject: [PATCH 1/5] feat: wip nanochat --- .../CartridgeLoader/Cartridges/NanoChatUi.cs | 27 +++++++ .../Cartridges/NanoChatUiFragment.xaml | 16 ++++ .../Cartridges/NanoChatUiFragment.xaml.cs | 31 ++++++++ .../Widgets/NanoChatChatsContainer.xaml | 25 ++++++ .../Widgets/NanoChatChatsContainer.xaml.cs | 21 +++++ .../Widgets/NanoChatMessageBox.xaml | 37 +++++++++ .../Widgets/NanoChatMessageBox.xaml.cs | 21 +++++ .../Widgets/NanoChatMessageEntry.xaml | 10 +++ .../Widgets/NanoChatMessageEntry.xaml.cs | 21 +++++ .../Cartridges/Widgets/NanoChatTopBar.xaml | 76 ++++++++++++++++++ .../Cartridges/Widgets/NanoChatTopBar.xaml.cs | 21 +++++ .../Cartridges/Widgets/NanoChatUserEntry.xaml | 30 ++++++++ .../Widgets/NanoChatUserEntry.xaml.cs | 22 ++++++ .../NanoChatCartridgeSystem.Events.cs | 38 +++++++++ .../NanoChatCartridgeSystem.Utils.cs | 26 +++++++ .../Cartridges/NanoChatCartridgeSystem.cs | 77 +++++++++++++++++++ .../_DEN/NanoChat/NanoChatCardSystem.cs | 6 ++ .../Cartridges/NanoChatCardComponent.cs | 51 ++++++++++++ .../Cartridges/NanoChatCartridgeComponent.cs | 14 ++++ .../Cartridges/NanoChatMessageType.cs | 7 ++ .../Cartridges/NanoChatUiMessageEvents.cs | 68 ++++++++++++++++ .../Cartridges/NanoChatUiState.cs | 10 +++ .../Entities/Objects/Devices/cartridges.yml | 17 ++++ 23 files changed, 672 insertions(+) create mode 100644 Content.Client/_DEN/CartridgeLoader/Cartridges/NanoChatUi.cs create mode 100644 Content.Client/_DEN/CartridgeLoader/Cartridges/NanoChatUiFragment.xaml create mode 100644 Content.Client/_DEN/CartridgeLoader/Cartridges/NanoChatUiFragment.xaml.cs create mode 100644 Content.Client/_DEN/CartridgeLoader/Cartridges/Widgets/NanoChatChatsContainer.xaml create mode 100644 Content.Client/_DEN/CartridgeLoader/Cartridges/Widgets/NanoChatChatsContainer.xaml.cs create mode 100644 Content.Client/_DEN/CartridgeLoader/Cartridges/Widgets/NanoChatMessageBox.xaml create mode 100644 Content.Client/_DEN/CartridgeLoader/Cartridges/Widgets/NanoChatMessageBox.xaml.cs create mode 100644 Content.Client/_DEN/CartridgeLoader/Cartridges/Widgets/NanoChatMessageEntry.xaml create mode 100644 Content.Client/_DEN/CartridgeLoader/Cartridges/Widgets/NanoChatMessageEntry.xaml.cs create mode 100644 Content.Client/_DEN/CartridgeLoader/Cartridges/Widgets/NanoChatTopBar.xaml create mode 100644 Content.Client/_DEN/CartridgeLoader/Cartridges/Widgets/NanoChatTopBar.xaml.cs create mode 100644 Content.Client/_DEN/CartridgeLoader/Cartridges/Widgets/NanoChatUserEntry.xaml create mode 100644 Content.Client/_DEN/CartridgeLoader/Cartridges/Widgets/NanoChatUserEntry.xaml.cs create mode 100644 Content.Server/_DEN/CartridgeLoader/Cartridges/NanoChatCartridgeSystem.Events.cs create mode 100644 Content.Server/_DEN/CartridgeLoader/Cartridges/NanoChatCartridgeSystem.Utils.cs create mode 100644 Content.Server/_DEN/CartridgeLoader/Cartridges/NanoChatCartridgeSystem.cs create mode 100644 Content.Server/_DEN/NanoChat/NanoChatCardSystem.cs create mode 100644 Content.Shared/_DEN/CartridgeLoader/Cartridges/NanoChatCardComponent.cs create mode 100644 Content.Shared/_DEN/CartridgeLoader/Cartridges/NanoChatCartridgeComponent.cs create mode 100644 Content.Shared/_DEN/CartridgeLoader/Cartridges/NanoChatMessageType.cs create mode 100644 Content.Shared/_DEN/CartridgeLoader/Cartridges/NanoChatUiMessageEvents.cs create mode 100644 Content.Shared/_DEN/CartridgeLoader/Cartridges/NanoChatUiState.cs create mode 100644 Resources/Prototypes/_DEN/Entities/Objects/Devices/cartridges.yml diff --git a/Content.Client/_DEN/CartridgeLoader/Cartridges/NanoChatUi.cs b/Content.Client/_DEN/CartridgeLoader/Cartridges/NanoChatUi.cs new file mode 100644 index 0000000000..a8e12191db --- /dev/null +++ b/Content.Client/_DEN/CartridgeLoader/Cartridges/NanoChatUi.cs @@ -0,0 +1,27 @@ +using Content.Client.UserInterface.Fragments; +using Content.Shared._DEN.CartridgeLoader.Cartridges; +using Robust.Client.UserInterface; + +namespace Content.Client._DEN.CartridgeLoader.Cartridges; + +public sealed partial class NanoChatUi : UIFragment +{ + private NanoChatUiFragment? _fragment; + public override Control GetUIFragmentRoot() + { + return _fragment!; + } + + public override void Setup(BoundUserInterface userInterface, EntityUid? fragmentOwner) + { + _fragment = new(); + } + + public override void UpdateState(BoundUserInterfaceState state) + { + if (state is not NanoChatUiState castState) + return; + + _fragment?.UpdateState(castState); + } +} diff --git a/Content.Client/_DEN/CartridgeLoader/Cartridges/NanoChatUiFragment.xaml b/Content.Client/_DEN/CartridgeLoader/Cartridges/NanoChatUiFragment.xaml new file mode 100644 index 0000000000..462c74c27a --- /dev/null +++ b/Content.Client/_DEN/CartridgeLoader/Cartridges/NanoChatUiFragment.xaml @@ -0,0 +1,16 @@ + + + + + + + + + diff --git a/Content.Client/_DEN/CartridgeLoader/Cartridges/NanoChatUiFragment.xaml.cs b/Content.Client/_DEN/CartridgeLoader/Cartridges/NanoChatUiFragment.xaml.cs new file mode 100644 index 0000000000..dbe8c28a27 --- /dev/null +++ b/Content.Client/_DEN/CartridgeLoader/Cartridges/NanoChatUiFragment.xaml.cs @@ -0,0 +1,31 @@ +using Content.Client._DEN.CartridgeLoader.Cartridges.Widgets; +using Content.Shared._DEN.CartridgeLoader.Cartridges; +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.XAML; + +namespace Content.Client._DEN.CartridgeLoader.Cartridges; + +[GenerateTypedNameReferences] +public sealed partial class NanoChatUiFragment : BoxContainer +{ + [Dependency] private readonly ILogManager _logManager = default!; + + private readonly Dictionary _conversations = new(); + private readonly Dictionary _messageIdToUi = new(); + + private ISawmill _sawmill; + + public NanoChatUiFragment() + { + RobustXamlLoader.Load(this); + IoCManager.InjectDependencies(this); + + _sawmill = _logManager.GetSawmill("nanochat.ui"); + } + + public void UpdateState(NanoChatUiState state) + { + + } +} diff --git a/Content.Client/_DEN/CartridgeLoader/Cartridges/Widgets/NanoChatChatsContainer.xaml b/Content.Client/_DEN/CartridgeLoader/Cartridges/Widgets/NanoChatChatsContainer.xaml new file mode 100644 index 0000000000..0a331677be --- /dev/null +++ b/Content.Client/_DEN/CartridgeLoader/Cartridges/Widgets/NanoChatChatsContainer.xaml @@ -0,0 +1,25 @@ + + + + + + + + + + diff --git a/Content.Client/_DEN/CartridgeLoader/Cartridges/Widgets/NanoChatChatsContainer.xaml.cs b/Content.Client/_DEN/CartridgeLoader/Cartridges/Widgets/NanoChatChatsContainer.xaml.cs new file mode 100644 index 0000000000..a665e4dd24 --- /dev/null +++ b/Content.Client/_DEN/CartridgeLoader/Cartridges/Widgets/NanoChatChatsContainer.xaml.cs @@ -0,0 +1,21 @@ +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.XAML; + +namespace Content.Client._DEN.CartridgeLoader.Cartridges.Widgets; + +[GenerateTypedNameReferences] +public sealed partial class NanoChatChatsContainer : BoxContainer +{ + [Dependency] private readonly ILogManager _logManager = default!; + + private ISawmill _sawmill = default!; + + public NanoChatChatsContainer() + { + RobustXamlLoader.Load(this); + IoCManager.InjectDependencies(this); + + _sawmill = _logManager.GetSawmill("nanochat.ui.chatscontainer"); + } +} diff --git a/Content.Client/_DEN/CartridgeLoader/Cartridges/Widgets/NanoChatMessageBox.xaml b/Content.Client/_DEN/CartridgeLoader/Cartridges/Widgets/NanoChatMessageBox.xaml new file mode 100644 index 0000000000..d86961c5cc --- /dev/null +++ b/Content.Client/_DEN/CartridgeLoader/Cartridges/Widgets/NanoChatMessageBox.xaml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + diff --git a/Content.Client/_DEN/CartridgeLoader/Cartridges/Widgets/NanoChatUserEntry.xaml.cs b/Content.Client/_DEN/CartridgeLoader/Cartridges/Widgets/NanoChatUserEntry.xaml.cs new file mode 100644 index 0000000000..5b9e31f0e6 --- /dev/null +++ b/Content.Client/_DEN/CartridgeLoader/Cartridges/Widgets/NanoChatUserEntry.xaml.cs @@ -0,0 +1,22 @@ +using Content.Shared._DEN.CartridgeLoader.Cartridges; +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.XAML; + +namespace Content.Client._DEN.CartridgeLoader.Cartridges.Widgets; + +[GenerateTypedNameReferences] +public sealed partial class NanoChatUserEntry : BoxContainer +{ + [Dependency] private readonly ILogManager _logManager = default!; + + private ISawmill _sawmill = default!; + + public NanoChatUserEntry() + { + RobustXamlLoader.Load(this); + IoCManager.InjectDependencies(this); + + _sawmill = _logManager.GetSawmill("nanochat.ui.entry"); + } +} diff --git a/Content.Server/_DEN/CartridgeLoader/Cartridges/NanoChatCartridgeSystem.Events.cs b/Content.Server/_DEN/CartridgeLoader/Cartridges/NanoChatCartridgeSystem.Events.cs new file mode 100644 index 0000000000..18885e17c1 --- /dev/null +++ b/Content.Server/_DEN/CartridgeLoader/Cartridges/NanoChatCartridgeSystem.Events.cs @@ -0,0 +1,38 @@ +using Content.Shared._DEN.CartridgeLoader.Cartridges; + +namespace Content.Server._DEN.CartridgeLoader.Cartridges; + +public sealed partial class NanoChatCartridgeSystem +{ + private void OnConversationCreated( + Entity cartridge, + NanoChatUiConversationCreatedEvent ev) + { + + } + + private void OnCheckedConversation( + Entity cartridge, + NanoChatUiCheckedConversationEvent ev) + { + + } + + private void OnMessageReceived(Entity cartridge, + NanoChatUiMessageReceivedEvent ev) + { + + } + + private void OnMessageEdited(Entity cartridge, + NanoChatUiMessageEditedEvent ev) + { + + } + + private void OnMessageDeleted(Entity cartridge, + NanoChatUiMessageDeletedEvent ev) + { + + } +} diff --git a/Content.Server/_DEN/CartridgeLoader/Cartridges/NanoChatCartridgeSystem.Utils.cs b/Content.Server/_DEN/CartridgeLoader/Cartridges/NanoChatCartridgeSystem.Utils.cs new file mode 100644 index 0000000000..6fe3d77ba1 --- /dev/null +++ b/Content.Server/_DEN/CartridgeLoader/Cartridges/NanoChatCartridgeSystem.Utils.cs @@ -0,0 +1,26 @@ +using System.Diagnostics.CodeAnalysis; +using Content.Shared._DEN.CartridgeLoader.Cartridges; +using Content.Shared.CartridgeLoader; + +namespace Content.Server._DEN.CartridgeLoader.Cartridges; + +public sealed partial class NanoChatCartridgeSystem +{ + public bool TryGetNanoChatCard(Entity ent, + [NotNullWhen(true)] out Entity? card) + { + card = null; + + if (ent.Comp.Card == null || !Exists(ent.Comp.Card) + || !TryComp(ent.Comp.Card, out var cardComp)) + return false; + + card = (ent.Comp.Card.Value, cardComp); + return true; + } + + private void UpdateCard(Entity ent) + { + + } +} diff --git a/Content.Server/_DEN/CartridgeLoader/Cartridges/NanoChatCartridgeSystem.cs b/Content.Server/_DEN/CartridgeLoader/Cartridges/NanoChatCartridgeSystem.cs new file mode 100644 index 0000000000..e08fd40d28 --- /dev/null +++ b/Content.Server/_DEN/CartridgeLoader/Cartridges/NanoChatCartridgeSystem.cs @@ -0,0 +1,77 @@ +using Content.Server.CartridgeLoader; +using Content.Shared._DEN.CartridgeLoader.Cartridges; +using Content.Shared.CartridgeLoader; +using Content.Shared.PDA; + +namespace Content.Server._DEN.CartridgeLoader.Cartridges; + +public sealed partial class NanoChatCartridgeSystem : EntitySystem +{ + [Dependency] private readonly CartridgeLoaderSystem _cartridgeLoaderSystem = null!; + + private Dictionary _users = new(); + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnUiReady); + SubscribeLocalEvent(OnUiMessage); + SubscribeLocalEvent(OnCartridgeParentChanged); + } + + private void OnCartridgeParentChanged(Entity ent, ref EntParentChangedMessage args) + { + + } + + private void OnUiReady(Entity ent, ref CartridgeUiReadyEvent args) + { + if (!TryGetNanoChatCard(ent, out var card)) + return; + + UpdateUiState(ent, args.Loader); + } + + private void OnUiMessage(Entity ent, ref CartridgeMessageEvent args) + { + if (args is not NanoChatUiMessageEvent message) + return; + + if (!TryGetNanoChatCard(ent, out var card)) + return; + + switch (message.Payload) + { + case NanoChatUiConversationCreatedEvent ev: + OnConversationCreated(card.Value, ev); + break; + case NanoChatUiCheckedConversationEvent ev: + OnCheckedConversation(card.Value, ev); + break; + case NanoChatUiMessageReceivedEvent ev: + OnMessageReceived(card.Value, ev); + break; + case NanoChatUiMessageEditedEvent ev: + OnMessageEdited(card.Value, ev); + break; + case NanoChatUiMessageDeletedEvent ev: + OnMessageDeleted(card.Value, ev); + break; + } + } + + private void UpdateUiState(Entity ent, EntityUid loader) + { + var state = new NanoChatUiState + { + Conversations = ent.Comp.Conversations, + Messages = ent.Comp.Messages, + Users = ent.Comp.Users, + SilencedConversations = ent.Comp.SilencedConversations, + UnreadMessages = ent.Comp.UnreadMessages + }; + + _cartridgeLoaderSystem.UpdateCartridgeUiState(loader, state); + } +} diff --git a/Content.Server/_DEN/NanoChat/NanoChatCardSystem.cs b/Content.Server/_DEN/NanoChat/NanoChatCardSystem.cs new file mode 100644 index 0000000000..3149dfbb54 --- /dev/null +++ b/Content.Server/_DEN/NanoChat/NanoChatCardSystem.cs @@ -0,0 +1,6 @@ +namespace Content.Server._DEN.NanoChat; + +public sealed class NanoChatCardSystem +{ + +} diff --git a/Content.Shared/_DEN/CartridgeLoader/Cartridges/NanoChatCardComponent.cs b/Content.Shared/_DEN/CartridgeLoader/Cartridges/NanoChatCardComponent.cs new file mode 100644 index 0000000000..1602eabc3d --- /dev/null +++ b/Content.Shared/_DEN/CartridgeLoader/Cartridges/NanoChatCardComponent.cs @@ -0,0 +1,51 @@ +using Robust.Shared.Serialization; + +namespace Content.Shared._DEN.CartridgeLoader.Cartridges; + +[RegisterComponent] +public sealed partial class NanoChatCardComponent : Component +{ + [ViewVariables] + public Dictionary Conversations { get; private set; } = new(); + + [ViewVariables] + public Dictionary Users { get; private set; } = new(); + + [ViewVariables] + public Dictionary Messages { get; private set; } = new(); + + [ViewVariables] + public HashSet SilencedConversations { get; set; } = new(); + + [ViewVariables] + public HashSet UnreadMessages { get; set; } = new(); +} + +[Serializable, NetSerializable] +public record struct NanoChatUser(int UniqueId, string Name, string Job); + +[Serializable, NetSerializable] +public record struct NanoChatConversation( + HashSet Members, + HashSet Messages); + +[Serializable, NetSerializable] +public record struct NanoChatMessage( + NanoChatUser Sender, + Guid ConversationId, + NanoChatMessageType MessageType, + HashSet SeenByUsers, + TimeSpan SentAt, + string Content); + +[ByRefEvent] +public record struct NanoChatNewConversationEvent(Guid ConversationId); + +[ByRefEvent] +public record struct NanoChatNewMessageEvent(NanoChatMessage Message); + +[ByRefEvent] +public record struct NanoChatEditMessageEvent(NanoChatMessage Message); + +[ByRefEvent] +public record struct NanoChatDeleteMessageEvent(NanoChatMessage Message); diff --git a/Content.Shared/_DEN/CartridgeLoader/Cartridges/NanoChatCartridgeComponent.cs b/Content.Shared/_DEN/CartridgeLoader/Cartridges/NanoChatCartridgeComponent.cs new file mode 100644 index 0000000000..c3bb5b5175 --- /dev/null +++ b/Content.Shared/_DEN/CartridgeLoader/Cartridges/NanoChatCartridgeComponent.cs @@ -0,0 +1,14 @@ +using Content.Shared.Radio; +using Robust.Shared.Prototypes; + +namespace Content.Shared._DEN.CartridgeLoader.Cartridges; + +[RegisterComponent] +public sealed partial class NanoChatCartridgeComponent : Component +{ + [DataField] + public EntityUid? Card; + + [DataField] + public ProtoId RadioChannel = "Common"; +} diff --git a/Content.Shared/_DEN/CartridgeLoader/Cartridges/NanoChatMessageType.cs b/Content.Shared/_DEN/CartridgeLoader/Cartridges/NanoChatMessageType.cs new file mode 100644 index 0000000000..b547b9f852 --- /dev/null +++ b/Content.Shared/_DEN/CartridgeLoader/Cartridges/NanoChatMessageType.cs @@ -0,0 +1,7 @@ +namespace Content.Shared._DEN.CartridgeLoader.Cartridges; + +public enum NanoChatMessageType +{ + Text, + Embed +} diff --git a/Content.Shared/_DEN/CartridgeLoader/Cartridges/NanoChatUiMessageEvents.cs b/Content.Shared/_DEN/CartridgeLoader/Cartridges/NanoChatUiMessageEvents.cs new file mode 100644 index 0000000000..9f70bd1ce5 --- /dev/null +++ b/Content.Shared/_DEN/CartridgeLoader/Cartridges/NanoChatUiMessageEvents.cs @@ -0,0 +1,68 @@ +using Content.Shared.CartridgeLoader; +using Robust.Shared.Serialization; + +namespace Content.Shared._DEN.CartridgeLoader.Cartridges; + +public interface INanoChatUiMessageEvent; + +[Serializable, NetSerializable] +public sealed class NanoChatUiMessageEvent(INanoChatUiMessageEvent payload) : CartridgeMessageEvent +{ + public readonly INanoChatUiMessageEvent Payload = payload; +} + +/// +/// An event called by group chats and when someone new sends you a message. +/// +/// The conversation ID. +/// The members in the conversation. +[Serializable, NetSerializable] +public sealed class NanoChatUiConversationCreatedEvent( + Guid conversationId, + HashSet members) : INanoChatUiMessageEvent +{ + [ViewVariables] + public Guid ConversationId = conversationId; + + [ViewVariables] + public HashSet Members = members; +} + +[Serializable, NetSerializable] +public sealed class NanoChatUiMessageReceivedEvent(NanoChatMessage message) : INanoChatUiMessageEvent +{ + [ViewVariables] + public NanoChatMessage Message = message; +} + +[Serializable, NetSerializable] +public sealed class NanoChatUiMessageEditedEvent( + Guid messageId, + string newContent) : INanoChatUiMessageEvent +{ + [ViewVariables] + public Guid MessageId = messageId; + + [ViewVariables] + public string NewContent = newContent; +} + +[Serializable, NetSerializable] +public sealed class NanoChatUiMessageDeletedEvent( + Guid messageId) : INanoChatUiMessageEvent +{ + [ViewVariables] + public Guid MessageId = messageId; +} + +[Serializable, NetSerializable] +public sealed class NanoChatUiCheckedConversationEvent( + Guid conversationId, + uint seenById) : INanoChatUiMessageEvent +{ + [ViewVariables] + public Guid ConversationId = conversationId; + + [ViewVariables] + public uint SeenById = seenById; +} diff --git a/Content.Shared/_DEN/CartridgeLoader/Cartridges/NanoChatUiState.cs b/Content.Shared/_DEN/CartridgeLoader/Cartridges/NanoChatUiState.cs new file mode 100644 index 0000000000..f51fb90348 --- /dev/null +++ b/Content.Shared/_DEN/CartridgeLoader/Cartridges/NanoChatUiState.cs @@ -0,0 +1,10 @@ +namespace Content.Shared._DEN.CartridgeLoader.Cartridges; + +public sealed class NanoChatUiState : BoundUserInterfaceState +{ + public Dictionary Conversations = new(); + public Dictionary Users = new(); + public Dictionary Messages = new(); + public HashSet SilencedConversations = new(); + public HashSet UnreadMessages = new(); +} diff --git a/Resources/Prototypes/_DEN/Entities/Objects/Devices/cartridges.yml b/Resources/Prototypes/_DEN/Entities/Objects/Devices/cartridges.yml new file mode 100644 index 0000000000..af52410a6d --- /dev/null +++ b/Resources/Prototypes/_DEN/Entities/Objects/Devices/cartridges.yml @@ -0,0 +1,17 @@ +- type: entity + parent: BaseItem + id: NanoChatCartridge + name: NanoChat cartridge + description: A social program for your PDA. + components: + - type: Sprite + sprite: Objects/Devices/cartridge.rsi + state: cart-nav + - type: Cartridge + programName: nano-task-program-name + icon: + sprite: Interface/Misc/program_icons.rsi + state: nano_task + - type: UIFragment + ui: !type:NanoChatUi + - type: NanoChatCartridge \ No newline at end of file From 3a41be7a839e57b8d397ed17e4490acc2a13b548 Mon Sep 17 00:00:00 2001 From: sleepyyapril Date: Sat, 8 Nov 2025 14:55:34 -0400 Subject: [PATCH 2/5] feat: more work --- Content.Client/_DEN/NanoChat/NanoChatCardSystem.cs | 5 +++++ Content.Server/_DEN/NanoChat/NanoChatCardSystem.cs | 6 ++++-- Content.Shared/_DEN/NanoChat/SharedNanoChatCardSystem.cs | 6 ++++++ 3 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 Content.Client/_DEN/NanoChat/NanoChatCardSystem.cs create mode 100644 Content.Shared/_DEN/NanoChat/SharedNanoChatCardSystem.cs diff --git a/Content.Client/_DEN/NanoChat/NanoChatCardSystem.cs b/Content.Client/_DEN/NanoChat/NanoChatCardSystem.cs new file mode 100644 index 0000000000..578ffb5c3c --- /dev/null +++ b/Content.Client/_DEN/NanoChat/NanoChatCardSystem.cs @@ -0,0 +1,5 @@ +using Content.Shared._DEN.NanoChat; + +namespace Content.Client._DEN.NanoChat; + +public sealed class NanoChatCardSystem : SharedNanoChatCardSystem; diff --git a/Content.Server/_DEN/NanoChat/NanoChatCardSystem.cs b/Content.Server/_DEN/NanoChat/NanoChatCardSystem.cs index 3149dfbb54..7361a9cba0 100644 --- a/Content.Server/_DEN/NanoChat/NanoChatCardSystem.cs +++ b/Content.Server/_DEN/NanoChat/NanoChatCardSystem.cs @@ -1,6 +1,8 @@ +using Content.Shared._DEN.NanoChat; + namespace Content.Server._DEN.NanoChat; -public sealed class NanoChatCardSystem +public sealed partial class NanoChatCardSystem : SharedNanoChatCardSystem { - + } diff --git a/Content.Shared/_DEN/NanoChat/SharedNanoChatCardSystem.cs b/Content.Shared/_DEN/NanoChat/SharedNanoChatCardSystem.cs new file mode 100644 index 0000000000..a534a4bebd --- /dev/null +++ b/Content.Shared/_DEN/NanoChat/SharedNanoChatCardSystem.cs @@ -0,0 +1,6 @@ +namespace Content.Shared._DEN.NanoChat; + +public abstract partial class SharedNanoChatCardSystem : EntitySystem +{ + +} From b8cb87e7212b943a4b029ca67fba2ae5875807bc Mon Sep 17 00:00:00 2001 From: sleepyyapril Date: Sun, 9 Nov 2025 11:11:36 -0400 Subject: [PATCH 3/5] feat: backend stuff mostly --- .../NanoChatCartridgeSystem.Events.cs | 45 +++++++-- .../NanoChatCartridgeSystem.Utils.cs | 19 +++- .../Cartridges/NanoChatCartridgeSystem.cs | 37 ++++---- .../_DEN/NanoChat/NanoChatCardSystem.Sync.cs | 91 ++++++++++++++++++ .../_DEN/NanoChat/NanoChatCardSystem.cs | 95 +++++++++++++++++++ .../Access/Systems/SharedIdCardSystem.cs | 11 +++ .../_DEN/Access/Systems/IdCardUpdatedEvent.cs | 11 +++ .../Cartridges/NanoChatCardComponent.cs | 60 +++++++++--- .../Cartridges/NanoChatUiMessageEvents.cs | 33 ++++--- .../Cartridges/NanoChatUiState.cs | 7 +- .../SharedNanoChatCardSystem.Helpers.cs | 45 +++++++++ .../_DEN/NanoChat/SharedNanoChatCardSystem.cs | 24 +++++ .../Locale/en-US/_DEN/nanochat/nanochat.ftl | 2 + .../_DEN/name_identifier_groups.yml | 3 + 14 files changed, 420 insertions(+), 63 deletions(-) create mode 100644 Content.Server/_DEN/NanoChat/NanoChatCardSystem.Sync.cs create mode 100644 Content.Shared/_DEN/Access/Systems/IdCardUpdatedEvent.cs create mode 100644 Content.Shared/_DEN/NanoChat/SharedNanoChatCardSystem.Helpers.cs create mode 100644 Resources/Locale/en-US/_DEN/nanochat/nanochat.ftl create mode 100644 Resources/Prototypes/_DEN/name_identifier_groups.yml diff --git a/Content.Server/_DEN/CartridgeLoader/Cartridges/NanoChatCartridgeSystem.Events.cs b/Content.Server/_DEN/CartridgeLoader/Cartridges/NanoChatCartridgeSystem.Events.cs index 18885e17c1..5d69355bd9 100644 --- a/Content.Server/_DEN/CartridgeLoader/Cartridges/NanoChatCartridgeSystem.Events.cs +++ b/Content.Server/_DEN/CartridgeLoader/Cartridges/NanoChatCartridgeSystem.Events.cs @@ -1,36 +1,61 @@ +using System.Linq; using Content.Shared._DEN.CartridgeLoader.Cartridges; namespace Content.Server._DEN.CartridgeLoader.Cartridges; public sealed partial class NanoChatCartridgeSystem { - private void OnConversationCreated( - Entity cartridge, + private void OnAttemptConversationCreated( + Entity ent, NanoChatUiConversationCreatedEvent ev) { + var attemptEv = new NanoChatAttemptContactEvent(ev.Members); + RaiseLocalEvent(ref attemptEv); + if (attemptEv.Cancelled) + return; + + var conversationId = Guid.NewGuid(); + var conversation = new NanoChatConversation(conversationId, + attemptEv.Targets, + [], + NanoChatConversationFlags.None); + + var successEvent = new NanoChatNewConversationEvent(conversation); + RaiseLocalEvent(successEvent); } - private void OnCheckedConversation( - Entity cartridge, - NanoChatUiCheckedConversationEvent ev) + private void OnSetCurrentConversation( + Entity ent, + NanoChatUiSetCurrentConversationEvent ev) { - + if (ev.ConversationId == null) + { + ent.Comp.CurrentChat = null; + UpdateUiState(ent); + return; + } + + if (!ent.Comp.Conversations.TryGetValue(ev.ConversationId.Value, out _)) + return; + + ent.Comp.CurrentChat = ev.ConversationId; + UpdateUiState(ent); } - private void OnMessageReceived(Entity cartridge, - NanoChatUiMessageReceivedEvent ev) + private void OnAttemptMessageSent(Entity ent, + NanoChatUiMessageSentEvent ev) { } - private void OnMessageEdited(Entity cartridge, + private void OnMessageEdited(Entity ent, NanoChatUiMessageEditedEvent ev) { } - private void OnMessageDeleted(Entity cartridge, + private void OnMessageDeleted(Entity ent, NanoChatUiMessageDeletedEvent ev) { diff --git a/Content.Server/_DEN/CartridgeLoader/Cartridges/NanoChatCartridgeSystem.Utils.cs b/Content.Server/_DEN/CartridgeLoader/Cartridges/NanoChatCartridgeSystem.Utils.cs index 6fe3d77ba1..445c3360c0 100644 --- a/Content.Server/_DEN/CartridgeLoader/Cartridges/NanoChatCartridgeSystem.Utils.cs +++ b/Content.Server/_DEN/CartridgeLoader/Cartridges/NanoChatCartridgeSystem.Utils.cs @@ -1,11 +1,15 @@ using System.Diagnostics.CodeAnalysis; using Content.Shared._DEN.CartridgeLoader.Cartridges; -using Content.Shared.CartridgeLoader; namespace Content.Server._DEN.CartridgeLoader.Cartridges; public sealed partial class NanoChatCartridgeSystem { + public bool CanMessageUser(Entity ent, uint target) + { + return true; + } + public bool TryGetNanoChatCard(Entity ent, [NotNullWhen(true)] out Entity? card) { @@ -19,8 +23,19 @@ public bool TryGetNanoChatCard(Entity ent, return true; } - private void UpdateCard(Entity ent) + private bool TryUpdateCard(Entity ent, + [NotNullWhen(true)] out Entity? resultCard) { + if (!TryGetNanoChatCard(ent, out var maybeCard) + || maybeCard is not { } card) + { + ent.Comp.Card = null; + resultCard = null; + return false; + } + ent.Comp.Card = card; + resultCard = card; + return true; } } diff --git a/Content.Server/_DEN/CartridgeLoader/Cartridges/NanoChatCartridgeSystem.cs b/Content.Server/_DEN/CartridgeLoader/Cartridges/NanoChatCartridgeSystem.cs index e08fd40d28..9a31134d4b 100644 --- a/Content.Server/_DEN/CartridgeLoader/Cartridges/NanoChatCartridgeSystem.cs +++ b/Content.Server/_DEN/CartridgeLoader/Cartridges/NanoChatCartridgeSystem.cs @@ -9,28 +9,20 @@ public sealed partial class NanoChatCartridgeSystem : EntitySystem { [Dependency] private readonly CartridgeLoaderSystem _cartridgeLoaderSystem = null!; - private Dictionary _users = new(); - public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnUiReady); SubscribeLocalEvent(OnUiMessage); - SubscribeLocalEvent(OnCartridgeParentChanged); - } - - private void OnCartridgeParentChanged(Entity ent, ref EntParentChangedMessage args) - { - } private void OnUiReady(Entity ent, ref CartridgeUiReadyEvent args) { - if (!TryGetNanoChatCard(ent, out var card)) + if (!TryUpdateCard(ent, out var card)) return; - UpdateUiState(ent, args.Loader); + UpdateUiState(card.Value, args.Loader); } private void OnUiMessage(Entity ent, ref CartridgeMessageEvent args) @@ -38,19 +30,19 @@ private void OnUiMessage(Entity ent, ref CartridgeMe if (args is not NanoChatUiMessageEvent message) return; - if (!TryGetNanoChatCard(ent, out var card)) + if (!TryUpdateCard(ent, out var card)) return; switch (message.Payload) { case NanoChatUiConversationCreatedEvent ev: - OnConversationCreated(card.Value, ev); + OnAttemptConversationCreated(card.Value, ev); break; - case NanoChatUiCheckedConversationEvent ev: - OnCheckedConversation(card.Value, ev); + case NanoChatUiSetCurrentConversationEvent ev: + OnSetCurrentConversation(card.Value, ev); break; - case NanoChatUiMessageReceivedEvent ev: - OnMessageReceived(card.Value, ev); + case NanoChatUiMessageSentEvent ev: + OnAttemptMessageSent(card.Value, ev); break; case NanoChatUiMessageEditedEvent ev: OnMessageEdited(card.Value, ev); @@ -61,15 +53,22 @@ private void OnUiMessage(Entity ent, ref CartridgeMe } } + public void UpdateUiState(Entity ent) + { + if (ent.Comp.LoaderUid == null || !Exists(ent.Comp.LoaderUid.Value)) + return; + + UpdateUiState(ent, ent.Comp.LoaderUid.Value); + } + private void UpdateUiState(Entity ent, EntityUid loader) { var state = new NanoChatUiState { Conversations = ent.Comp.Conversations, Messages = ent.Comp.Messages, - Users = ent.Comp.Users, - SilencedConversations = ent.Comp.SilencedConversations, - UnreadMessages = ent.Comp.UnreadMessages + RelevantUsers = ent.Comp.RelevantUsers, + UnreadMessages = ent.Comp.UnreadMessages, }; _cartridgeLoaderSystem.UpdateCartridgeUiState(loader, state); diff --git a/Content.Server/_DEN/NanoChat/NanoChatCardSystem.Sync.cs b/Content.Server/_DEN/NanoChat/NanoChatCardSystem.Sync.cs new file mode 100644 index 0000000000..0784aa345a --- /dev/null +++ b/Content.Server/_DEN/NanoChat/NanoChatCardSystem.Sync.cs @@ -0,0 +1,91 @@ +using Content.Shared._DEN.CartridgeLoader.Cartridges; + +namespace Content.Server._DEN.NanoChat; + +public sealed partial class NanoChatCardSystem +{ + private readonly Dictionary _users = new(); + private readonly HashSet _updatedUsers = new(); + + public void InitializeSync() + { + SubscribeLocalEvent(OnUsersUpdated); + SubscribeLocalEvent(OnNewConversation); + SubscribeLocalEvent(OnUpdatedConversation); + SubscribeLocalEvent(OnNewMessage); + SubscribeLocalEvent(OnMessageChanged); + SubscribeLocalEvent(OnMessageDeleted); + } + + private void SyncConversation(NanoChatConversation conversation) + { + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out var card)) + { + if (card.PersonalNumber == null || card.LoaderUid == null) + continue; + + var sendConversation = conversation.Members.Contains(card.PersonalNumber.Value); + + if (!sendConversation) + continue; + + card.Conversations[conversation.ConversationId] = conversation; + _nanoChatCartridge.UpdateUiState((uid, card), card.LoaderUid.Value); + } + } + + private void SyncConversationFromMessage(Entity ent, NanoChatMessage message) + { + var hasConversation = ent.Comp.Conversations.TryGetValue(message.ConversationId, out var conversation); + + if (!hasConversation) + return; + + SyncConversation(conversation); + } + + private void OnNewConversation(Entity ent, ref NanoChatNewConversationEvent args) + { + SyncConversation(args.Conversation); + } + + private void OnUpdatedConversation(Entity ent, ref NanoChatUpdatedConversationEvent args) + { + SyncConversation(args.Conversation); + } + + private void OnNewMessage(Entity ent, ref NanoChatNewMessageEvent args) + { + SyncConversationFromMessage(ent, args.Message); + } + + private void OnMessageChanged(Entity ent, ref NanoChatMessageChangedEvent args) + { + SyncConversationFromMessage(ent, args.NewMessage); + } + + private void OnMessageDeleted(Entity ent, ref NanoChatDeleteMessageEvent args) + { + if (!ent.Comp.Messages.Remove(args.MessageId, out var message)) + return; + + SyncConversationFromMessage(ent, message); + } + + private void OnUsersUpdated(Entity ent, ref NanoChatUsersUpdatedEvent ev) + { + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out var card)) + { + foreach (var nanoChatId in _updatedUsers) + { + if (!card.RelevantUsers.TryGetValue(nanoChatId, out _)) + continue; + + card.RelevantUsers[nanoChatId] = ev.RelevantUsers[nanoChatId]; + Dirty(uid, card); + } + } + } +} diff --git a/Content.Server/_DEN/NanoChat/NanoChatCardSystem.cs b/Content.Server/_DEN/NanoChat/NanoChatCardSystem.cs index 7361a9cba0..edbb7546c9 100644 --- a/Content.Server/_DEN/NanoChat/NanoChatCardSystem.cs +++ b/Content.Server/_DEN/NanoChat/NanoChatCardSystem.cs @@ -1,8 +1,103 @@ +using System.Linq; +using Content.Server._DEN.CartridgeLoader.Cartridges; +using Content.Server.NameIdentifier; +using Content.Shared._DEN.Access.Systems; +using Content.Shared._DEN.CartridgeLoader.Cartridges; using Content.Shared._DEN.NanoChat; +using Content.Shared.Access.Components; +using Content.Shared.NameIdentifier; +using Content.Shared.PDA; +using Robust.Shared.Containers; +using Robust.Shared.Prototypes; +using Robust.Shared.Utility; namespace Content.Server._DEN.NanoChat; public sealed partial class NanoChatCardSystem : SharedNanoChatCardSystem { + [Dependency] private readonly NameIdentifierSystem _nameIdentifier = null!; + [Dependency] private readonly NanoChatCartridgeSystem _nanoChatCartridge = null!; + private const string DefaultFullName = "Unknown"; + private const string DefaultJobTitle = "Unknown"; + + private readonly ProtoId _nanoChatIds = "NanoChatIds"; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnMapInit); + SubscribeLocalEvent(OnCardInserted); + SubscribeLocalEvent(OnCardRemoved); + SubscribeLocalEvent(OnNameUpdated); + SubscribeLocalEvent(OnJobTitleUpdated); + + // Synchronizing messages, conversations, users + InitializeSync(); + } + + private void OnMapInit(Entity ent, ref MapInitEvent args) + { + if (ent.Comp.PersonalNumber != null) + return; + + _nameIdentifier.GenerateUniqueName(ent, _nanoChatIds, out var number); + var nanoChatId = (uint) number; + SetNumber(ent.AsNullable(), nanoChatId); + CacheUser(ent, nanoChatId); + } + + private void OnCardInserted(Entity ent, ref EntGotInsertedIntoContainerMessage msg) + { + if (msg.Container.ID != PdaComponent.PdaIdSlotId) + return; + + ent.Comp.LoaderUid = msg.Container.Owner; + Dirty(ent); + } + + private void OnCardRemoved(Entity ent, ref EntGotRemovedFromContainerMessage msg) + { + if (msg.Container.ID != PdaComponent.PdaIdSlotId) + return; + + ent.Comp.LoaderUid = null; + Dirty(ent); + } + + private void OnNameUpdated(Entity ent, ref IdCardNameUpdatedEvent args) + { + if (ent.Comp.PersonalNumber == null + || !_users.TryGetValue(ent.Comp.PersonalNumber.Value, out _)) + return; + + CacheUser(ent, ent.Comp.PersonalNumber.Value); + } + + private void OnJobTitleUpdated(Entity ent, ref IdCardJobTitleUpdatedEvent args) + { + if (ent.Comp.PersonalNumber == null + || !_users.TryGetValue(ent.Comp.PersonalNumber.Value, out _)) + return; + + CacheUser(ent, ent.Comp.PersonalNumber.Value); + } + + private void CacheUser(Entity ent, uint nanoChatId) + { + if (!TryComp(ent, out var idCard)) + return; + + var name = idCard.FullName ?? DefaultFullName; + var jobTitle = idCard.LocalizedJobTitle ?? DefaultJobTitle; + + var newUser = new NanoChatUser(nanoChatId, name, jobTitle); + _users[newUser.UniqueId] = newUser; + _updatedUsers.Add(nanoChatId); + + var usersClone = _users.ShallowClone(); + var ev = new NanoChatUsersUpdatedEvent(usersClone); + RaiseLocalEvent(ref ev); + } } diff --git a/Content.Shared/Access/Systems/SharedIdCardSystem.cs b/Content.Shared/Access/Systems/SharedIdCardSystem.cs index 513abb20ee..4ead643c3e 100644 --- a/Content.Shared/Access/Systems/SharedIdCardSystem.cs +++ b/Content.Shared/Access/Systems/SharedIdCardSystem.cs @@ -1,4 +1,5 @@ using System.Globalization; +using Content.Shared._DEN.Access.Systems; using Content.Shared.Access.Components; using Content.Shared.Administration.Logs; using Content.Shared.CCVar; @@ -155,6 +156,11 @@ public bool TryChangeJobTitle(EntityUid uid, string? jobTitle, IdCardComponent? Dirty(uid, id); UpdateEntityName(uid, id); + // Start DEN: raise an event on ID card updating + var ev = new IdCardJobTitleUpdatedEvent(jobTitle); + RaiseLocalEvent(ev); + // End DEN + if (player != null) { _adminLogger.Add(LogType.Identity, LogImpact.Low, @@ -249,6 +255,11 @@ public bool TryChangeFullName(EntityUid uid, string? fullName, IdCardComponent? Dirty(uid, id); UpdateEntityName(uid, id); + // Start DEN: raise an event on ID card updating + var ev = new IdCardNameUpdatedEvent(fullName); + RaiseLocalEvent(ev); + // End DEN + if (player != null) { _adminLogger.Add(LogType.Identity, LogImpact.Low, diff --git a/Content.Shared/_DEN/Access/Systems/IdCardUpdatedEvent.cs b/Content.Shared/_DEN/Access/Systems/IdCardUpdatedEvent.cs new file mode 100644 index 0000000000..79579e336c --- /dev/null +++ b/Content.Shared/_DEN/Access/Systems/IdCardUpdatedEvent.cs @@ -0,0 +1,11 @@ +namespace Content.Shared._DEN.Access.Systems; + +public sealed class IdCardNameUpdatedEvent(string? newName) : EntityEventArgs +{ + public string? NewName { get; set; } = newName; +} + +public sealed class IdCardJobTitleUpdatedEvent(string? newJobTitle) : EntityEventArgs +{ + public string? NewJobTitle { get; set; } = newJobTitle; +} diff --git a/Content.Shared/_DEN/CartridgeLoader/Cartridges/NanoChatCardComponent.cs b/Content.Shared/_DEN/CartridgeLoader/Cartridges/NanoChatCardComponent.cs index 1602eabc3d..f173b59adf 100644 --- a/Content.Shared/_DEN/CartridgeLoader/Cartridges/NanoChatCardComponent.cs +++ b/Content.Shared/_DEN/CartridgeLoader/Cartridges/NanoChatCardComponent.cs @@ -5,47 +5,83 @@ namespace Content.Shared._DEN.CartridgeLoader.Cartridges; [RegisterComponent] public sealed partial class NanoChatCardComponent : Component { - [ViewVariables] - public Dictionary Conversations { get; private set; } = new(); + [DataField] + public bool ListNumber { get; set; } = true; [ViewVariables] - public Dictionary Users { get; private set; } = new(); + public EntityUid? LoaderUid { get; set; } [ViewVariables] - public Dictionary Messages { get; private set; } = new(); + public uint? PersonalNumber { get; set; } [ViewVariables] - public HashSet SilencedConversations { get; set; } = new(); + public Guid? CurrentChat { get; set; } [ViewVariables] public HashSet UnreadMessages { get; set; } = new(); + + [ViewVariables] + public Dictionary Conversations { get; private set; } = new(); + + [ViewVariables] + public Dictionary RelevantUsers { get; private set; } = new(); + + [ViewVariables] + public Dictionary Messages { get; private set; } = new(); } [Serializable, NetSerializable] -public record struct NanoChatUser(int UniqueId, string Name, string Job); +public record struct NanoChatUser(uint UniqueId, string Name, string Job); [Serializable, NetSerializable] public record struct NanoChatConversation( - HashSet Members, - HashSet Messages); + Guid ConversationId, + HashSet Members, + HashSet Messages, + NanoChatConversationFlags Flags); [Serializable, NetSerializable] public record struct NanoChatMessage( NanoChatUser Sender, Guid ConversationId, + NanoChatMessageFlags Flags, NanoChatMessageType MessageType, - HashSet SeenByUsers, + HashSet SeenByUsers, TimeSpan SentAt, string Content); +public enum NanoChatMessageFlags : byte +{ + None = 0, + Blocked = 1, + FailedToSend = 2, +} + +public enum NanoChatConversationFlags : byte +{ + None = 0, + Silenced = 1 +} + +[ByRefEvent] +public record struct NanoChatAttemptContactEvent(HashSet Targets, bool Cancelled = false); + +public sealed class NanoChatNewConversationEvent(NanoChatConversation conversation) : EntityEventArgs +{ + public NanoChatConversation Conversation { get; } = conversation; +} + +[ByRefEvent] +public record struct NanoChatUpdatedConversationEvent(NanoChatConversation Conversation); + [ByRefEvent] -public record struct NanoChatNewConversationEvent(Guid ConversationId); +public record struct NanoChatUsersUpdatedEvent(Dictionary RelevantUsers); [ByRefEvent] public record struct NanoChatNewMessageEvent(NanoChatMessage Message); [ByRefEvent] -public record struct NanoChatEditMessageEvent(NanoChatMessage Message); +public record struct NanoChatMessageChangedEvent(NanoChatMessage NewMessage); [ByRefEvent] -public record struct NanoChatDeleteMessageEvent(NanoChatMessage Message); +public record struct NanoChatDeleteMessageEvent(Guid MessageId); diff --git a/Content.Shared/_DEN/CartridgeLoader/Cartridges/NanoChatUiMessageEvents.cs b/Content.Shared/_DEN/CartridgeLoader/Cartridges/NanoChatUiMessageEvents.cs index 9f70bd1ce5..59369513f3 100644 --- a/Content.Shared/_DEN/CartridgeLoader/Cartridges/NanoChatUiMessageEvents.cs +++ b/Content.Shared/_DEN/CartridgeLoader/Cartridges/NanoChatUiMessageEvents.cs @@ -12,27 +12,30 @@ public sealed class NanoChatUiMessageEvent(INanoChatUiMessageEvent payload) : Ca } /// -/// An event called by group chats and when someone new sends you a message. +/// An event called by trying to create a group chat or message someone new. /// -/// The conversation ID. /// The members in the conversation. [Serializable, NetSerializable] -public sealed class NanoChatUiConversationCreatedEvent( - Guid conversationId, - HashSet members) : INanoChatUiMessageEvent +public sealed class NanoChatUiConversationCreatedEvent(HashSet members) : INanoChatUiMessageEvent { - [ViewVariables] - public Guid ConversationId = conversationId; - [ViewVariables] public HashSet Members = members; } [Serializable, NetSerializable] -public sealed class NanoChatUiMessageReceivedEvent(NanoChatMessage message) : INanoChatUiMessageEvent +public sealed class NanoChatUiMessageSentEvent( + NanoChatMessageType messageType, + TimeSpan sentAt, + string content) : INanoChatUiMessageEvent { [ViewVariables] - public NanoChatMessage Message = message; + public NanoChatMessageType MessageType = messageType; + + [ViewVariables] + public TimeSpan SentAt = sentAt; + + [ViewVariables] + public string Content = content; } [Serializable, NetSerializable] @@ -56,13 +59,9 @@ public sealed class NanoChatUiMessageDeletedEvent( } [Serializable, NetSerializable] -public sealed class NanoChatUiCheckedConversationEvent( - Guid conversationId, - uint seenById) : INanoChatUiMessageEvent +public sealed class NanoChatUiSetCurrentConversationEvent( + Guid? conversationId) : INanoChatUiMessageEvent { [ViewVariables] - public Guid ConversationId = conversationId; - - [ViewVariables] - public uint SeenById = seenById; + public Guid? ConversationId = conversationId; } diff --git a/Content.Shared/_DEN/CartridgeLoader/Cartridges/NanoChatUiState.cs b/Content.Shared/_DEN/CartridgeLoader/Cartridges/NanoChatUiState.cs index f51fb90348..1f435cf6ac 100644 --- a/Content.Shared/_DEN/CartridgeLoader/Cartridges/NanoChatUiState.cs +++ b/Content.Shared/_DEN/CartridgeLoader/Cartridges/NanoChatUiState.cs @@ -2,9 +2,10 @@ namespace Content.Shared._DEN.CartridgeLoader.Cartridges; public sealed class NanoChatUiState : BoundUserInterfaceState { + public uint PersonalNumber; + public HashSet UnreadMessages = new(); + public Dictionary Conversations = new(); - public Dictionary Users = new(); + public Dictionary RelevantUsers = new(); public Dictionary Messages = new(); - public HashSet SilencedConversations = new(); - public HashSet UnreadMessages = new(); } diff --git a/Content.Shared/_DEN/NanoChat/SharedNanoChatCardSystem.Helpers.cs b/Content.Shared/_DEN/NanoChat/SharedNanoChatCardSystem.Helpers.cs new file mode 100644 index 0000000000..340418a2e9 --- /dev/null +++ b/Content.Shared/_DEN/NanoChat/SharedNanoChatCardSystem.Helpers.cs @@ -0,0 +1,45 @@ +using System.Diagnostics.CodeAnalysis; +using Content.Shared._DEN.CartridgeLoader.Cartridges; + +namespace Content.Shared._DEN.NanoChat; + +public abstract partial class SharedNanoChatCardSystem +{ + private uint? GetNumber(Entity ent) + { + if (!Resolve(ent, ref ent.Comp)) + return null; + + return ent.Comp.PersonalNumber; + } + + public bool TryGetNumber(Entity ent, + [NotNullWhen(true)] out uint? number) + { + number = GetNumber(ent); + return number != null; + } + + public void SetNumber(Entity ent, uint number) + { + if (!Resolve(ent, ref ent.Comp)) + return; + + ent.Comp.PersonalNumber = number; + Dirty(ent); + } + + private bool TryGetNanoChatLoader(Entity ent, + out EntityUid? loaderUid) + { + if (!Resolve(ent, ref ent.Comp) + || ent.Comp.LoaderUid == null || !Exists(ent.Comp.LoaderUid)) + { + loaderUid = null; + return false; + } + + loaderUid = ent.Comp.LoaderUid; + return true; + } +} diff --git a/Content.Shared/_DEN/NanoChat/SharedNanoChatCardSystem.cs b/Content.Shared/_DEN/NanoChat/SharedNanoChatCardSystem.cs index a534a4bebd..5dcb275688 100644 --- a/Content.Shared/_DEN/NanoChat/SharedNanoChatCardSystem.cs +++ b/Content.Shared/_DEN/NanoChat/SharedNanoChatCardSystem.cs @@ -1,6 +1,30 @@ +using Content.Shared._DEN.CartridgeLoader.Cartridges; +using Content.Shared.Examine; + namespace Content.Shared._DEN.NanoChat; public abstract partial class SharedNanoChatCardSystem : EntitySystem { + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnExamined); + } + + private void OnExamined(Entity ent, ref ExaminedEvent args) + { + if (!args.IsInDetailsRange) + return; + + if (ent.Comp.PersonalNumber == null) + { + var noNumberExamineText = Loc.GetString("nanochat-card-examine-no-number"); + args.PushMarkup(noNumberExamineText); + return; + } + var examineText = Loc.GetString("nanochat-card-examine-has-number", ("number", ent.Comp.PersonalNumber)); + args.PushMarkup(examineText); + } } diff --git a/Resources/Locale/en-US/_DEN/nanochat/nanochat.ftl b/Resources/Locale/en-US/_DEN/nanochat/nanochat.ftl new file mode 100644 index 0000000000..6bca67688c --- /dev/null +++ b/Resources/Locale/en-US/_DEN/nanochat/nanochat.ftl @@ -0,0 +1,2 @@ +nanochat-card-examine-no-number = This card has no number. +nanochat-card-examine-has-number = Number: [color=white]{$number}[/color] \ No newline at end of file diff --git a/Resources/Prototypes/_DEN/name_identifier_groups.yml b/Resources/Prototypes/_DEN/name_identifier_groups.yml new file mode 100644 index 0000000000..81a83990de --- /dev/null +++ b/Resources/Prototypes/_DEN/name_identifier_groups.yml @@ -0,0 +1,3 @@ +- type: nameIdentifierGroup + id: NanoChatIds + maxValue: 9999 \ No newline at end of file From b5ad3c85475fceff408ec26a55bc43f3c36429b1 Mon Sep 17 00:00:00 2001 From: sleepyyapril Date: Wed, 19 Nov 2025 22:21:25 -0400 Subject: [PATCH 4/5] a --- ...ry.xaml => NanoChatConversationEntry.xaml} | 0 ...l.cs => NanoChatConversationEntry.xaml.cs} | 2 + .../_DEN/NanoChat/NanoChatCardSystem.cs | 5 - .../NanoChatCartridgeSystem.Events.cs | 63 ----------- .../NanoChatCartridgeSystem.Utils.cs | 41 ------- .../Cartridges/NanoChatCartridgeSystem.cs | 76 ------------- .../_DEN/NanoChat/NanoChatCardSystem.Sync.cs | 91 ---------------- .../_DEN/NanoChat/NanoChatCardSystem.cs | 103 ------------------ .../Cartridges/NanoChatMessageType.cs | 7 -- Content.Shared/_DEN/NanoChat/NanoChat.cs | 6 + .../SharedNanoChatCardSystem.Helpers.cs | 45 -------- .../_DEN/NanoChat/SharedNanoChatCardSystem.cs | 30 ----- 12 files changed, 8 insertions(+), 461 deletions(-) rename Content.Client/_DEN/CartridgeLoader/Cartridges/Widgets/{NanoChatUserEntry.xaml => NanoChatConversationEntry.xaml} (100%) rename Content.Client/_DEN/CartridgeLoader/Cartridges/Widgets/{NanoChatUserEntry.xaml.cs => NanoChatConversationEntry.xaml.cs} (94%) delete mode 100644 Content.Client/_DEN/NanoChat/NanoChatCardSystem.cs delete mode 100644 Content.Server/_DEN/CartridgeLoader/Cartridges/NanoChatCartridgeSystem.Events.cs delete mode 100644 Content.Server/_DEN/CartridgeLoader/Cartridges/NanoChatCartridgeSystem.Utils.cs delete mode 100644 Content.Server/_DEN/CartridgeLoader/Cartridges/NanoChatCartridgeSystem.cs delete mode 100644 Content.Server/_DEN/NanoChat/NanoChatCardSystem.Sync.cs delete mode 100644 Content.Server/_DEN/NanoChat/NanoChatCardSystem.cs delete mode 100644 Content.Shared/_DEN/CartridgeLoader/Cartridges/NanoChatMessageType.cs create mode 100644 Content.Shared/_DEN/NanoChat/NanoChat.cs delete mode 100644 Content.Shared/_DEN/NanoChat/SharedNanoChatCardSystem.Helpers.cs delete mode 100644 Content.Shared/_DEN/NanoChat/SharedNanoChatCardSystem.cs diff --git a/Content.Client/_DEN/CartridgeLoader/Cartridges/Widgets/NanoChatUserEntry.xaml b/Content.Client/_DEN/CartridgeLoader/Cartridges/Widgets/NanoChatConversationEntry.xaml similarity index 100% rename from Content.Client/_DEN/CartridgeLoader/Cartridges/Widgets/NanoChatUserEntry.xaml rename to Content.Client/_DEN/CartridgeLoader/Cartridges/Widgets/NanoChatConversationEntry.xaml diff --git a/Content.Client/_DEN/CartridgeLoader/Cartridges/Widgets/NanoChatUserEntry.xaml.cs b/Content.Client/_DEN/CartridgeLoader/Cartridges/Widgets/NanoChatConversationEntry.xaml.cs similarity index 94% rename from Content.Client/_DEN/CartridgeLoader/Cartridges/Widgets/NanoChatUserEntry.xaml.cs rename to Content.Client/_DEN/CartridgeLoader/Cartridges/Widgets/NanoChatConversationEntry.xaml.cs index 5b9e31f0e6..98cb53691b 100644 --- a/Content.Client/_DEN/CartridgeLoader/Cartridges/Widgets/NanoChatUserEntry.xaml.cs +++ b/Content.Client/_DEN/CartridgeLoader/Cartridges/Widgets/NanoChatConversationEntry.xaml.cs @@ -19,4 +19,6 @@ public NanoChatUserEntry() _sawmill = _logManager.GetSawmill("nanochat.ui.entry"); } + + public void SetConversationTitle() } diff --git a/Content.Client/_DEN/NanoChat/NanoChatCardSystem.cs b/Content.Client/_DEN/NanoChat/NanoChatCardSystem.cs deleted file mode 100644 index 578ffb5c3c..0000000000 --- a/Content.Client/_DEN/NanoChat/NanoChatCardSystem.cs +++ /dev/null @@ -1,5 +0,0 @@ -using Content.Shared._DEN.NanoChat; - -namespace Content.Client._DEN.NanoChat; - -public sealed class NanoChatCardSystem : SharedNanoChatCardSystem; diff --git a/Content.Server/_DEN/CartridgeLoader/Cartridges/NanoChatCartridgeSystem.Events.cs b/Content.Server/_DEN/CartridgeLoader/Cartridges/NanoChatCartridgeSystem.Events.cs deleted file mode 100644 index 5d69355bd9..0000000000 --- a/Content.Server/_DEN/CartridgeLoader/Cartridges/NanoChatCartridgeSystem.Events.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System.Linq; -using Content.Shared._DEN.CartridgeLoader.Cartridges; - -namespace Content.Server._DEN.CartridgeLoader.Cartridges; - -public sealed partial class NanoChatCartridgeSystem -{ - private void OnAttemptConversationCreated( - Entity ent, - NanoChatUiConversationCreatedEvent ev) - { - var attemptEv = new NanoChatAttemptContactEvent(ev.Members); - RaiseLocalEvent(ref attemptEv); - - if (attemptEv.Cancelled) - return; - - var conversationId = Guid.NewGuid(); - var conversation = new NanoChatConversation(conversationId, - attemptEv.Targets, - [], - NanoChatConversationFlags.None); - - var successEvent = new NanoChatNewConversationEvent(conversation); - RaiseLocalEvent(successEvent); - } - - private void OnSetCurrentConversation( - Entity ent, - NanoChatUiSetCurrentConversationEvent ev) - { - if (ev.ConversationId == null) - { - ent.Comp.CurrentChat = null; - UpdateUiState(ent); - return; - } - - if (!ent.Comp.Conversations.TryGetValue(ev.ConversationId.Value, out _)) - return; - - ent.Comp.CurrentChat = ev.ConversationId; - UpdateUiState(ent); - } - - private void OnAttemptMessageSent(Entity ent, - NanoChatUiMessageSentEvent ev) - { - - } - - private void OnMessageEdited(Entity ent, - NanoChatUiMessageEditedEvent ev) - { - - } - - private void OnMessageDeleted(Entity ent, - NanoChatUiMessageDeletedEvent ev) - { - - } -} diff --git a/Content.Server/_DEN/CartridgeLoader/Cartridges/NanoChatCartridgeSystem.Utils.cs b/Content.Server/_DEN/CartridgeLoader/Cartridges/NanoChatCartridgeSystem.Utils.cs deleted file mode 100644 index 445c3360c0..0000000000 --- a/Content.Server/_DEN/CartridgeLoader/Cartridges/NanoChatCartridgeSystem.Utils.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System.Diagnostics.CodeAnalysis; -using Content.Shared._DEN.CartridgeLoader.Cartridges; - -namespace Content.Server._DEN.CartridgeLoader.Cartridges; - -public sealed partial class NanoChatCartridgeSystem -{ - public bool CanMessageUser(Entity ent, uint target) - { - return true; - } - - public bool TryGetNanoChatCard(Entity ent, - [NotNullWhen(true)] out Entity? card) - { - card = null; - - if (ent.Comp.Card == null || !Exists(ent.Comp.Card) - || !TryComp(ent.Comp.Card, out var cardComp)) - return false; - - card = (ent.Comp.Card.Value, cardComp); - return true; - } - - private bool TryUpdateCard(Entity ent, - [NotNullWhen(true)] out Entity? resultCard) - { - if (!TryGetNanoChatCard(ent, out var maybeCard) - || maybeCard is not { } card) - { - ent.Comp.Card = null; - resultCard = null; - return false; - } - - ent.Comp.Card = card; - resultCard = card; - return true; - } -} diff --git a/Content.Server/_DEN/CartridgeLoader/Cartridges/NanoChatCartridgeSystem.cs b/Content.Server/_DEN/CartridgeLoader/Cartridges/NanoChatCartridgeSystem.cs deleted file mode 100644 index 9a31134d4b..0000000000 --- a/Content.Server/_DEN/CartridgeLoader/Cartridges/NanoChatCartridgeSystem.cs +++ /dev/null @@ -1,76 +0,0 @@ -using Content.Server.CartridgeLoader; -using Content.Shared._DEN.CartridgeLoader.Cartridges; -using Content.Shared.CartridgeLoader; -using Content.Shared.PDA; - -namespace Content.Server._DEN.CartridgeLoader.Cartridges; - -public sealed partial class NanoChatCartridgeSystem : EntitySystem -{ - [Dependency] private readonly CartridgeLoaderSystem _cartridgeLoaderSystem = null!; - - public override void Initialize() - { - base.Initialize(); - - SubscribeLocalEvent(OnUiReady); - SubscribeLocalEvent(OnUiMessage); - } - - private void OnUiReady(Entity ent, ref CartridgeUiReadyEvent args) - { - if (!TryUpdateCard(ent, out var card)) - return; - - UpdateUiState(card.Value, args.Loader); - } - - private void OnUiMessage(Entity ent, ref CartridgeMessageEvent args) - { - if (args is not NanoChatUiMessageEvent message) - return; - - if (!TryUpdateCard(ent, out var card)) - return; - - switch (message.Payload) - { - case NanoChatUiConversationCreatedEvent ev: - OnAttemptConversationCreated(card.Value, ev); - break; - case NanoChatUiSetCurrentConversationEvent ev: - OnSetCurrentConversation(card.Value, ev); - break; - case NanoChatUiMessageSentEvent ev: - OnAttemptMessageSent(card.Value, ev); - break; - case NanoChatUiMessageEditedEvent ev: - OnMessageEdited(card.Value, ev); - break; - case NanoChatUiMessageDeletedEvent ev: - OnMessageDeleted(card.Value, ev); - break; - } - } - - public void UpdateUiState(Entity ent) - { - if (ent.Comp.LoaderUid == null || !Exists(ent.Comp.LoaderUid.Value)) - return; - - UpdateUiState(ent, ent.Comp.LoaderUid.Value); - } - - private void UpdateUiState(Entity ent, EntityUid loader) - { - var state = new NanoChatUiState - { - Conversations = ent.Comp.Conversations, - Messages = ent.Comp.Messages, - RelevantUsers = ent.Comp.RelevantUsers, - UnreadMessages = ent.Comp.UnreadMessages, - }; - - _cartridgeLoaderSystem.UpdateCartridgeUiState(loader, state); - } -} diff --git a/Content.Server/_DEN/NanoChat/NanoChatCardSystem.Sync.cs b/Content.Server/_DEN/NanoChat/NanoChatCardSystem.Sync.cs deleted file mode 100644 index 0784aa345a..0000000000 --- a/Content.Server/_DEN/NanoChat/NanoChatCardSystem.Sync.cs +++ /dev/null @@ -1,91 +0,0 @@ -using Content.Shared._DEN.CartridgeLoader.Cartridges; - -namespace Content.Server._DEN.NanoChat; - -public sealed partial class NanoChatCardSystem -{ - private readonly Dictionary _users = new(); - private readonly HashSet _updatedUsers = new(); - - public void InitializeSync() - { - SubscribeLocalEvent(OnUsersUpdated); - SubscribeLocalEvent(OnNewConversation); - SubscribeLocalEvent(OnUpdatedConversation); - SubscribeLocalEvent(OnNewMessage); - SubscribeLocalEvent(OnMessageChanged); - SubscribeLocalEvent(OnMessageDeleted); - } - - private void SyncConversation(NanoChatConversation conversation) - { - var query = EntityQueryEnumerator(); - while (query.MoveNext(out var uid, out var card)) - { - if (card.PersonalNumber == null || card.LoaderUid == null) - continue; - - var sendConversation = conversation.Members.Contains(card.PersonalNumber.Value); - - if (!sendConversation) - continue; - - card.Conversations[conversation.ConversationId] = conversation; - _nanoChatCartridge.UpdateUiState((uid, card), card.LoaderUid.Value); - } - } - - private void SyncConversationFromMessage(Entity ent, NanoChatMessage message) - { - var hasConversation = ent.Comp.Conversations.TryGetValue(message.ConversationId, out var conversation); - - if (!hasConversation) - return; - - SyncConversation(conversation); - } - - private void OnNewConversation(Entity ent, ref NanoChatNewConversationEvent args) - { - SyncConversation(args.Conversation); - } - - private void OnUpdatedConversation(Entity ent, ref NanoChatUpdatedConversationEvent args) - { - SyncConversation(args.Conversation); - } - - private void OnNewMessage(Entity ent, ref NanoChatNewMessageEvent args) - { - SyncConversationFromMessage(ent, args.Message); - } - - private void OnMessageChanged(Entity ent, ref NanoChatMessageChangedEvent args) - { - SyncConversationFromMessage(ent, args.NewMessage); - } - - private void OnMessageDeleted(Entity ent, ref NanoChatDeleteMessageEvent args) - { - if (!ent.Comp.Messages.Remove(args.MessageId, out var message)) - return; - - SyncConversationFromMessage(ent, message); - } - - private void OnUsersUpdated(Entity ent, ref NanoChatUsersUpdatedEvent ev) - { - var query = EntityQueryEnumerator(); - while (query.MoveNext(out var uid, out var card)) - { - foreach (var nanoChatId in _updatedUsers) - { - if (!card.RelevantUsers.TryGetValue(nanoChatId, out _)) - continue; - - card.RelevantUsers[nanoChatId] = ev.RelevantUsers[nanoChatId]; - Dirty(uid, card); - } - } - } -} diff --git a/Content.Server/_DEN/NanoChat/NanoChatCardSystem.cs b/Content.Server/_DEN/NanoChat/NanoChatCardSystem.cs deleted file mode 100644 index edbb7546c9..0000000000 --- a/Content.Server/_DEN/NanoChat/NanoChatCardSystem.cs +++ /dev/null @@ -1,103 +0,0 @@ -using System.Linq; -using Content.Server._DEN.CartridgeLoader.Cartridges; -using Content.Server.NameIdentifier; -using Content.Shared._DEN.Access.Systems; -using Content.Shared._DEN.CartridgeLoader.Cartridges; -using Content.Shared._DEN.NanoChat; -using Content.Shared.Access.Components; -using Content.Shared.NameIdentifier; -using Content.Shared.PDA; -using Robust.Shared.Containers; -using Robust.Shared.Prototypes; -using Robust.Shared.Utility; - -namespace Content.Server._DEN.NanoChat; - -public sealed partial class NanoChatCardSystem : SharedNanoChatCardSystem -{ - [Dependency] private readonly NameIdentifierSystem _nameIdentifier = null!; - [Dependency] private readonly NanoChatCartridgeSystem _nanoChatCartridge = null!; - - private const string DefaultFullName = "Unknown"; - private const string DefaultJobTitle = "Unknown"; - - private readonly ProtoId _nanoChatIds = "NanoChatIds"; - - public override void Initialize() - { - base.Initialize(); - - SubscribeLocalEvent(OnMapInit); - SubscribeLocalEvent(OnCardInserted); - SubscribeLocalEvent(OnCardRemoved); - SubscribeLocalEvent(OnNameUpdated); - SubscribeLocalEvent(OnJobTitleUpdated); - - // Synchronizing messages, conversations, users - InitializeSync(); - } - - private void OnMapInit(Entity ent, ref MapInitEvent args) - { - if (ent.Comp.PersonalNumber != null) - return; - - _nameIdentifier.GenerateUniqueName(ent, _nanoChatIds, out var number); - var nanoChatId = (uint) number; - SetNumber(ent.AsNullable(), nanoChatId); - CacheUser(ent, nanoChatId); - } - - private void OnCardInserted(Entity ent, ref EntGotInsertedIntoContainerMessage msg) - { - if (msg.Container.ID != PdaComponent.PdaIdSlotId) - return; - - ent.Comp.LoaderUid = msg.Container.Owner; - Dirty(ent); - } - - private void OnCardRemoved(Entity ent, ref EntGotRemovedFromContainerMessage msg) - { - if (msg.Container.ID != PdaComponent.PdaIdSlotId) - return; - - ent.Comp.LoaderUid = null; - Dirty(ent); - } - - private void OnNameUpdated(Entity ent, ref IdCardNameUpdatedEvent args) - { - if (ent.Comp.PersonalNumber == null - || !_users.TryGetValue(ent.Comp.PersonalNumber.Value, out _)) - return; - - CacheUser(ent, ent.Comp.PersonalNumber.Value); - } - - private void OnJobTitleUpdated(Entity ent, ref IdCardJobTitleUpdatedEvent args) - { - if (ent.Comp.PersonalNumber == null - || !_users.TryGetValue(ent.Comp.PersonalNumber.Value, out _)) - return; - - CacheUser(ent, ent.Comp.PersonalNumber.Value); - } - - private void CacheUser(Entity ent, uint nanoChatId) - { - if (!TryComp(ent, out var idCard)) - return; - - var name = idCard.FullName ?? DefaultFullName; - var jobTitle = idCard.LocalizedJobTitle ?? DefaultJobTitle; - - var newUser = new NanoChatUser(nanoChatId, name, jobTitle); - _users[newUser.UniqueId] = newUser; - _updatedUsers.Add(nanoChatId); - - var usersClone = _users.ShallowClone(); - var ev = new NanoChatUsersUpdatedEvent(usersClone); - RaiseLocalEvent(ref ev); - } -} diff --git a/Content.Shared/_DEN/CartridgeLoader/Cartridges/NanoChatMessageType.cs b/Content.Shared/_DEN/CartridgeLoader/Cartridges/NanoChatMessageType.cs deleted file mode 100644 index b547b9f852..0000000000 --- a/Content.Shared/_DEN/CartridgeLoader/Cartridges/NanoChatMessageType.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Content.Shared._DEN.CartridgeLoader.Cartridges; - -public enum NanoChatMessageType -{ - Text, - Embed -} diff --git a/Content.Shared/_DEN/NanoChat/NanoChat.cs b/Content.Shared/_DEN/NanoChat/NanoChat.cs new file mode 100644 index 0000000000..3e01f6ed80 --- /dev/null +++ b/Content.Shared/_DEN/NanoChat/NanoChat.cs @@ -0,0 +1,6 @@ +namespace Content.Shared._DEN.NanoChat; + +public sealed class NanoChat +{ + +} diff --git a/Content.Shared/_DEN/NanoChat/SharedNanoChatCardSystem.Helpers.cs b/Content.Shared/_DEN/NanoChat/SharedNanoChatCardSystem.Helpers.cs deleted file mode 100644 index 340418a2e9..0000000000 --- a/Content.Shared/_DEN/NanoChat/SharedNanoChatCardSystem.Helpers.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System.Diagnostics.CodeAnalysis; -using Content.Shared._DEN.CartridgeLoader.Cartridges; - -namespace Content.Shared._DEN.NanoChat; - -public abstract partial class SharedNanoChatCardSystem -{ - private uint? GetNumber(Entity ent) - { - if (!Resolve(ent, ref ent.Comp)) - return null; - - return ent.Comp.PersonalNumber; - } - - public bool TryGetNumber(Entity ent, - [NotNullWhen(true)] out uint? number) - { - number = GetNumber(ent); - return number != null; - } - - public void SetNumber(Entity ent, uint number) - { - if (!Resolve(ent, ref ent.Comp)) - return; - - ent.Comp.PersonalNumber = number; - Dirty(ent); - } - - private bool TryGetNanoChatLoader(Entity ent, - out EntityUid? loaderUid) - { - if (!Resolve(ent, ref ent.Comp) - || ent.Comp.LoaderUid == null || !Exists(ent.Comp.LoaderUid)) - { - loaderUid = null; - return false; - } - - loaderUid = ent.Comp.LoaderUid; - return true; - } -} diff --git a/Content.Shared/_DEN/NanoChat/SharedNanoChatCardSystem.cs b/Content.Shared/_DEN/NanoChat/SharedNanoChatCardSystem.cs deleted file mode 100644 index 5dcb275688..0000000000 --- a/Content.Shared/_DEN/NanoChat/SharedNanoChatCardSystem.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Content.Shared._DEN.CartridgeLoader.Cartridges; -using Content.Shared.Examine; - -namespace Content.Shared._DEN.NanoChat; - -public abstract partial class SharedNanoChatCardSystem : EntitySystem -{ - public override void Initialize() - { - base.Initialize(); - - SubscribeLocalEvent(OnExamined); - } - - private void OnExamined(Entity ent, ref ExaminedEvent args) - { - if (!args.IsInDetailsRange) - return; - - if (ent.Comp.PersonalNumber == null) - { - var noNumberExamineText = Loc.GetString("nanochat-card-examine-no-number"); - args.PushMarkup(noNumberExamineText); - return; - } - - var examineText = Loc.GetString("nanochat-card-examine-has-number", ("number", ent.Comp.PersonalNumber)); - args.PushMarkup(examineText); - } -} From 19c6567465fcf95bd1129b7f444f85b891c941bb Mon Sep 17 00:00:00 2001 From: sleepyyapril Date: Wed, 19 Nov 2025 22:21:29 -0400 Subject: [PATCH 5/5] a --- .../Cartridges/NanoChatUiFragment.xaml.cs | 17 ++++- .../Widgets/NanoChatChatsContainer.xaml.cs | 25 ++++++- .../Widgets/NanoChatConversationEntry.xaml | 7 +- .../Widgets/NanoChatConversationEntry.xaml.cs | 29 ++++++- Content.Server/Content.Server.csproj | 3 + .../Cartridges/NanoChatCardComponent.cs | 75 +------------------ .../Cartridges/NanoChatUiMessageEvents.cs | 5 ++ .../Cartridges/NanoChatUiState.cs | 5 +- Content.Shared/_DEN/NanoChat/NanoChat.cs | 68 ++++++++++++++++- 9 files changed, 147 insertions(+), 87 deletions(-) diff --git a/Content.Client/_DEN/CartridgeLoader/Cartridges/NanoChatUiFragment.xaml.cs b/Content.Client/_DEN/CartridgeLoader/Cartridges/NanoChatUiFragment.xaml.cs index dbe8c28a27..b7a3513c60 100644 --- a/Content.Client/_DEN/CartridgeLoader/Cartridges/NanoChatUiFragment.xaml.cs +++ b/Content.Client/_DEN/CartridgeLoader/Cartridges/NanoChatUiFragment.xaml.cs @@ -1,5 +1,6 @@ using Content.Client._DEN.CartridgeLoader.Cartridges.Widgets; using Content.Shared._DEN.CartridgeLoader.Cartridges; +using Content.Shared._DEN.NanoChat; using Robust.Client.AutoGenerated; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.XAML; @@ -11,9 +12,10 @@ public sealed partial class NanoChatUiFragment : BoxContainer { [Dependency] private readonly ILogManager _logManager = default!; - private readonly Dictionary _conversations = new(); - private readonly Dictionary _messageIdToUi = new(); - + private Dictionary _conversations = new(); + private Dictionary _messages = new(); + private Dictionary _users = new(); + private Dictionary _messageIdToUi = new(); private ISawmill _sawmill; public NanoChatUiFragment() @@ -26,6 +28,15 @@ public NanoChatUiFragment() public void UpdateState(NanoChatUiState state) { + _conversations = state.Conversations; + _messages = state.Messages; + _users = state.RelevantUsers; + + ChatsContainer.SetConversations(state.Conversations, state.CurrentConversationId); + } + private void AddMessageEntry(Guid messageId, NanoChatMessageEntry messageEntry) + { + _messageIdToUi.Add(messageId, messageEntry); } } diff --git a/Content.Client/_DEN/CartridgeLoader/Cartridges/Widgets/NanoChatChatsContainer.xaml.cs b/Content.Client/_DEN/CartridgeLoader/Cartridges/Widgets/NanoChatChatsContainer.xaml.cs index a665e4dd24..fc3a85f831 100644 --- a/Content.Client/_DEN/CartridgeLoader/Cartridges/Widgets/NanoChatChatsContainer.xaml.cs +++ b/Content.Client/_DEN/CartridgeLoader/Cartridges/Widgets/NanoChatChatsContainer.xaml.cs @@ -1,3 +1,4 @@ +using Content.Shared._DEN.NanoChat; using Robust.Client.AutoGenerated; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.XAML; @@ -9,7 +10,9 @@ public sealed partial class NanoChatChatsContainer : BoxContainer { [Dependency] private readonly ILogManager _logManager = default!; - private ISawmill _sawmill = default!; + private readonly ISawmill _sawmill; + + public event Action? OnChatClicked; public NanoChatChatsContainer() { @@ -18,4 +21,24 @@ public NanoChatChatsContainer() _sawmill = _logManager.GetSawmill("nanochat.ui.chatscontainer"); } + + public void SetConversations(Dictionary conversations, + Guid? currentConversationId = null) + { + foreach (var pair in conversations) + { + BuildConversation(pair.Value, currentConversationId == pair.Key); + } + } + + private void BuildConversation(NanoChatConversation conversation, bool pressed) + { + var userEntry = new NanoChatConversationEntry(); + + userEntry.SetConversationTitle(conversation.Title); + userEntry.SetConversationSubtitle(conversation.Subtitle); + userEntry.SetPressed(pressed); + + userEntry.OnConversationClicked += () => OnChatClicked?.Invoke(conversation.Id); + } } diff --git a/Content.Client/_DEN/CartridgeLoader/Cartridges/Widgets/NanoChatConversationEntry.xaml b/Content.Client/_DEN/CartridgeLoader/Cartridges/Widgets/NanoChatConversationEntry.xaml index 3414c422fb..c2b84f1476 100644 --- a/Content.Client/_DEN/CartridgeLoader/Cartridges/Widgets/NanoChatConversationEntry.xaml +++ b/Content.Client/_DEN/CartridgeLoader/Cartridges/Widgets/NanoChatConversationEntry.xaml @@ -8,7 +8,8 @@ -