using Content.Shared.DeltaV.CartridgeLoader.Cartridges; using Content.Shared.Examine; using Content.Shared.PDA; using Robust.Shared.Timing; namespace Content.Shared.DeltaV.NanoChat; /// /// Base system for NanoChat functionality shared between client and server. /// public abstract class SharedNanoChatSystem : EntitySystem { [Dependency] private readonly IGameTiming _timing = default!; public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnExamined); } private void OnExamined(Entity ent, ref ExaminedEvent args) { if (!args.IsInDetailsRange) return; if (ent.Comp.Number == null) { args.PushMarkup(Loc.GetString("nanochat-card-examine-no-number")); return; } args.PushMarkup(Loc.GetString("nanochat-card-examine-number", ("number", $"{ent.Comp.Number:D4}"))); } #region Public API Methods /// /// Gets the NanoChat number for a card. /// public uint? GetNumber(Entity card) { if (!Resolve(card, ref card.Comp)) return null; return card.Comp.Number; } /// /// Sets the NanoChat number for a card. /// public void SetNumber(Entity card, uint number) { if (!Resolve(card, ref card.Comp)) return; card.Comp.Number = number; Dirty(card); } /// /// Gets the recipients dictionary from a card. /// public IReadOnlyDictionary GetRecipients(Entity card) { if (!Resolve(card, ref card.Comp)) return new Dictionary(); return card.Comp.Recipients; } /// /// Gets the messages dictionary from a card. /// public IReadOnlyDictionary> GetMessages(Entity card) { if (!Resolve(card, ref card.Comp)) return new Dictionary>(); return card.Comp.Messages; } /// /// Sets a specific recipient in the card. /// public void SetRecipient(Entity card, uint number, NanoChatRecipient recipient) { if (!Resolve(card, ref card.Comp)) return; card.Comp.Recipients[number] = recipient; Dirty(card); } /// /// Gets a specific recipient from the card. /// public NanoChatRecipient? GetRecipient(Entity card, uint number) { if (!Resolve(card, ref card.Comp) || !card.Comp.Recipients.TryGetValue(number, out var recipient)) return null; return recipient; } /// /// Gets all messages for a specific recipient. /// public List? GetMessagesForRecipient(Entity card, uint recipientNumber) { if (!Resolve(card, ref card.Comp) || !card.Comp.Messages.TryGetValue(recipientNumber, out var messages)) return null; return new List(messages); } /// /// Adds a message to a recipient's conversation. /// public void AddMessage(Entity card, uint recipientNumber, NanoChatMessage message) { if (!Resolve(card, ref card.Comp)) return; if (!card.Comp.Messages.TryGetValue(recipientNumber, out var messages)) { messages = new List(); card.Comp.Messages[recipientNumber] = messages; } messages.Add(message); card.Comp.LastMessageTime = _timing.CurTime; Dirty(card); } /// /// Gets the currently selected chat recipient. /// public uint? GetCurrentChat(Entity card) { if (!Resolve(card, ref card.Comp)) return null; return card.Comp.CurrentChat; } /// /// Sets the currently selected chat recipient. /// public void SetCurrentChat(Entity card, uint? recipient) { if (!Resolve(card, ref card.Comp)) return; card.Comp.CurrentChat = recipient; Dirty(card); } /// /// Gets whether notifications are muted. /// public bool GetNotificationsMuted(Entity card) { if (!Resolve(card, ref card.Comp)) return false; return card.Comp.NotificationsMuted; } /// /// Sets whether notifications are muted. /// public void SetNotificationsMuted(Entity card, bool muted) { if (!Resolve(card, ref card.Comp)) return; card.Comp.NotificationsMuted = muted; Dirty(card); } /// /// Gets the time of the last message. /// public TimeSpan? GetLastMessageTime(Entity card) { if (!Resolve(card, ref card.Comp)) return null; return card.Comp.LastMessageTime; } /// /// Gets if there are unread messages from a recipient. /// public bool HasUnreadMessages(Entity card, uint recipientNumber) { if (!Resolve(card, ref card.Comp) || !card.Comp.Recipients.TryGetValue(recipientNumber, out var recipient)) return false; return recipient.HasUnread; } /// /// Clears all messages and recipients from the card. /// public void Clear(Entity card) { if (!Resolve(card, ref card.Comp)) return; card.Comp.Messages.Clear(); card.Comp.Recipients.Clear(); card.Comp.CurrentChat = null; Dirty(card); } /// /// Deletes a chat conversation with a recipient from the card. /// Optionally keeps message history while removing from active chats. /// /// True if the chat was deleted successfully public bool TryDeleteChat(Entity card, uint recipientNumber, bool keepMessages = false) { if (!Resolve(card, ref card.Comp)) return false; // Remove from recipients list var removed = card.Comp.Recipients.Remove(recipientNumber); // Clear messages if requested if (!keepMessages) card.Comp.Messages.Remove(recipientNumber); // Clear current chat if we just deleted it if (card.Comp.CurrentChat == recipientNumber) card.Comp.CurrentChat = null; if (removed) Dirty(card); return removed; } /// /// Ensures a recipient exists in the card's contacts and message lists. /// If the recipient doesn't exist, they will be added with the provided info. /// /// True if the recipient was added or already existed public bool EnsureRecipientExists(Entity card, uint recipientNumber, NanoChatRecipient? recipientInfo = null) { if (!Resolve(card, ref card.Comp)) return false; if (!card.Comp.Recipients.ContainsKey(recipientNumber)) { // Only add if we have recipient info if (recipientInfo == null) return false; card.Comp.Recipients[recipientNumber] = recipientInfo.Value; } // Ensure message list exists for this recipient if (!card.Comp.Messages.ContainsKey(recipientNumber)) card.Comp.Messages[recipientNumber] = new List(); Dirty(card); return true; } #endregion }