mirror of
https://github.com/WWhiteDreamProject/wwdpublic.git
synced 2026-04-17 05:27:38 +03:00
# Description
Fixes notifications so that they always trigger when the chat is not
open, fixes a possible exploit where a user can send a message that is
longer than the max message length, and improves the UX of NanoChat in a
few areas.
Original message from
https://github.com/Goob-Station/Goob-Station/pull/1313:
> Fixed NanoChat message notifications not showing up in situations
where you'd definitely expect them to occur.
>
> Now, for a chat to not send a notification upon a new message, three
conditions need to be fulfilled:
> - You don't have the chat muted
> - Your PDA UI is open
> - You have NanoChat as your open program
> - Your currently-selected chat is the aforementioned chat
More changes:
- Validate NanoChat message length & chat name/job title length on the
server
c063001ca9.
-If they are too long, they will be truncated to the maximum length.
- Improve the UI for editing a chat:
- Added a proper icon (used to be the letter E) for the Edit Chat
button.

- The Edit Chat popup now has correct text: the title is now "Edit a
contact", not "Add a new chat" and the Create button has been renamed to
the Confirm button.

- Editing a chat no longer deselects the current chat.
- This is done by adding a new NanoChatUiMessageType entry, `EditChat`
and a new server-side handler function just for chat edits. The previous
edit chat method simply *deleted* the chat from the client and created a
new one.
- Form validation is now more robust: you can now only submit the edit
if you've made changes to the name or job title.
- Fixed NanoChat not appearing in PDAs with more than 5 pre-installed
programs by increasing the PDA disk space (max program count) from 5 to
8, the current disk space in Wizden.

- The job title now appears on the notification title.

- The title will be truncated if it's too long.

- Improved form validation on the New Chat popup by only allowing users
to submit if the Number field is 4 numbers long. Previously, inputs like
"0" "12" "289" were valid which is ultimately incorrect as phone numbers
function more like strings that just happen to be digit-only and less
like actual numbers.

- The left chat list will now truncate names and job titles if they're
too long.

## Changelog
🆑 Skubman
- add: NanoChat message notifications will now show you the job title of
the sender alongside their name.
- add: The NanoChat edit button now has a proper icon.
- tweak: The disk space (max amount of installable programs) on PDAs has
been increased from 5 to 8. This also fixes a bug where NanoChat was not
being installed on PDAs with more than 5 pre-installed cartridges.
- tweak: The character limit for names and job titles in NanoChat has
been increased to their actual limit on ID cards (30 characters).
- tweak: NanoChat chat list names/titles and notification titles that
are too long will be shortened, indicated with "..." at the end.
- tweak: The NanoChat edit popup now displays the correct text, instead
of appearing identical to the new chat popup.
- fix: NanoChat will now send a new message notification no matter what
if you don't have the chat open.
- fix: Editing a chat in NanoChat no longer deselects that chat.
- fix: Fixed a issue where users could potentially send NanoChat
messages longer than the maximum allowed message length.
- fix: Fixed being able to create a new chat when you haven't typed in 4
digits in the number field.
(cherry picked from commit f11d2e7976491a5c95aeb36eaa7a313624197a88)
155 lines
5.2 KiB
C#
155 lines
5.2 KiB
C#
using System.Linq;
|
|
using Content.Server.Access.Systems;
|
|
using Content.Server.Administration.Logs;
|
|
using Content.Server.Kitchen.Components;
|
|
using Content.Server.NameIdentifier;
|
|
using Content.Shared.Database;
|
|
using Content.Shared.DeltaV.CartridgeLoader.Cartridges;
|
|
using Content.Shared.DeltaV.NanoChat;
|
|
using Content.Shared.NameIdentifier;
|
|
using Content.Shared.PDA;
|
|
using Robust.Shared.Containers;
|
|
using Robust.Shared.Prototypes;
|
|
using Robust.Shared.Random;
|
|
|
|
namespace Content.Server.DeltaV.NanoChat;
|
|
|
|
/// <summary>
|
|
/// Handles NanoChat features that are specific to the server but not related to the cartridge itself.
|
|
/// </summary>
|
|
public sealed class NanoChatSystem : SharedNanoChatSystem
|
|
{
|
|
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
|
|
[Dependency] private readonly IRobustRandom _random = default!;
|
|
[Dependency] private readonly NameIdentifierSystem _name = default!;
|
|
|
|
private readonly ProtoId<NameIdentifierGroupPrototype> _nameIdentifierGroup = "NanoChat";
|
|
|
|
public override void Initialize()
|
|
{
|
|
base.Initialize();
|
|
|
|
SubscribeLocalEvent<NanoChatCardComponent, EntGotInsertedIntoContainerMessage>(OnInserted);
|
|
SubscribeLocalEvent<NanoChatCardComponent, EntGotRemovedFromContainerMessage>(OnRemoved);
|
|
|
|
SubscribeLocalEvent<NanoChatCardComponent, MapInitEvent>(OnCardInit);
|
|
SubscribeLocalEvent<NanoChatCardComponent, BeingMicrowavedEvent>(OnMicrowaved, after: [typeof(IdCardSystem)]);
|
|
}
|
|
|
|
private void OnInserted(Entity<NanoChatCardComponent> ent, ref EntGotInsertedIntoContainerMessage args)
|
|
{
|
|
if (args.Container.ID != PdaComponent.PdaIdSlotId)
|
|
return;
|
|
|
|
ent.Comp.PdaUid = args.Container.Owner;
|
|
Dirty(ent);
|
|
}
|
|
|
|
private void OnRemoved(Entity<NanoChatCardComponent> ent, ref EntGotRemovedFromContainerMessage args)
|
|
{
|
|
if (args.Container.ID != PdaComponent.PdaIdSlotId)
|
|
return;
|
|
|
|
ent.Comp.PdaUid = null;
|
|
Dirty(ent);
|
|
}
|
|
|
|
private void OnMicrowaved(Entity<NanoChatCardComponent> ent, ref BeingMicrowavedEvent args)
|
|
{
|
|
// Skip if the entity was deleted (e.g., by ID card system burning it)
|
|
if (Deleted(ent))
|
|
return;
|
|
|
|
if (!TryComp<MicrowaveComponent>(args.Microwave, out var micro) || micro.Broken)
|
|
return;
|
|
|
|
var randomPick = _random.NextFloat();
|
|
|
|
// Super lucky - erase all messages (10% chance)
|
|
if (randomPick <= 0.10f)
|
|
{
|
|
ent.Comp.Messages.Clear();
|
|
// TODO: these shouldn't be shown at the same time as the popups from IdCardSystem
|
|
// _popup.PopupEntity(Loc.GetString("nanochat-card-microwave-erased", ("card", ent)),
|
|
// ent,
|
|
// PopupType.Medium);
|
|
|
|
_adminLogger.Add(LogType.Action,
|
|
LogImpact.Medium,
|
|
$"{ToPrettyString(args.Microwave)} erased all messages on {ToPrettyString(ent)}");
|
|
}
|
|
else
|
|
{
|
|
// Scramble random messages for random recipients
|
|
ScrambleMessages(ent);
|
|
// _popup.PopupEntity(Loc.GetString("nanochat-card-microwave-scrambled", ("card", ent)),
|
|
// ent,
|
|
// PopupType.Medium);
|
|
|
|
_adminLogger.Add(LogType.Action,
|
|
LogImpact.Medium,
|
|
$"{ToPrettyString(args.Microwave)} scrambled messages on {ToPrettyString(ent)}");
|
|
}
|
|
|
|
Dirty(ent);
|
|
}
|
|
|
|
private void ScrambleMessages(NanoChatCardComponent component)
|
|
{
|
|
foreach (var (recipientNumber, messages) in component.Messages)
|
|
{
|
|
for (var i = 0; i < messages.Count; i++)
|
|
{
|
|
// 50% chance to scramble each message
|
|
if (!_random.Prob(0.5f))
|
|
continue;
|
|
|
|
var message = messages[i];
|
|
message.Content = ScrambleText(message.Content);
|
|
messages[i] = message;
|
|
}
|
|
|
|
// 25% chance to reassign the conversation to a random recipient
|
|
if (_random.Prob(0.25f) && component.Recipients.Count > 0)
|
|
{
|
|
var newRecipient = _random.Pick(component.Recipients.Keys.ToList());
|
|
if (newRecipient == recipientNumber)
|
|
continue;
|
|
|
|
if (!component.Messages.ContainsKey(newRecipient))
|
|
component.Messages[newRecipient] = new List<NanoChatMessage>();
|
|
|
|
component.Messages[newRecipient].AddRange(messages);
|
|
component.Messages[recipientNumber].Clear();
|
|
}
|
|
}
|
|
}
|
|
|
|
private string ScrambleText(string text)
|
|
{
|
|
var chars = text.ToCharArray();
|
|
var n = chars.Length;
|
|
|
|
// Fisher-Yates shuffle of characters
|
|
while (n > 1)
|
|
{
|
|
n--;
|
|
var k = _random.Next(n + 1);
|
|
(chars[k], chars[n]) = (chars[n], chars[k]);
|
|
}
|
|
|
|
return new string(chars);
|
|
}
|
|
|
|
private void OnCardInit(Entity<NanoChatCardComponent> ent, ref MapInitEvent args)
|
|
{
|
|
if (ent.Comp.Number != null)
|
|
return;
|
|
|
|
// Assign a random number
|
|
_name.GenerateUniqueName(ent, _nameIdentifierGroup, out var number);
|
|
ent.Comp.Number = (uint)number;
|
|
Dirty(ent);
|
|
}
|
|
}
|