feat(fax): Fax machines print, copy, and send paper labels (#25979)
* feat(fax): Client fax file-print parses and stores label * feat(fax): Fax machines print, copy, and send paper labels * style(Fax): Comments and formatting * feat(fax): Make fax admin logging more consistent and clear * refactor(fax): Replace ternary with a simpler null coalescing * refactor(fax): Make FaxSystem Send method signature consistent with Copy, PrintFile * refactor(fax): Read entire file and process later instead of peeking first * refactor(fax): Remove local variables only used for style * style(fax): Fix some nearby style errors * fix(fax): Undo an inaccurate change to admin log formatting * refactor(fax): Separate `firstLine` variable * fix(fax): Use Environment.NewLine * bienvenidos --------- Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
This commit is contained in:
@@ -52,8 +52,27 @@ public sealed class FaxBoundUi : BoundUserInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
using var reader = new StreamReader(file);
|
using var reader = new StreamReader(file);
|
||||||
|
|
||||||
|
var firstLine = await reader.ReadLineAsync();
|
||||||
|
string? label = null;
|
||||||
var content = await reader.ReadToEndAsync();
|
var content = await reader.ReadToEndAsync();
|
||||||
SendMessage(new FaxFileMessage(content[..Math.Min(content.Length, FaxFileMessageValidation.MaxContentSize)], _window.OfficePaper));
|
|
||||||
|
if (firstLine is { })
|
||||||
|
{
|
||||||
|
if (firstLine.StartsWith('#'))
|
||||||
|
{
|
||||||
|
label = firstLine[1..].Trim();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
content = firstLine + "\n" + content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SendMessage(new FaxFileMessage(
|
||||||
|
label?[..Math.Min(label.Length, FaxFileMessageValidation.MaxLabelSize)],
|
||||||
|
content[..Math.Min(content.Length, FaxFileMessageValidation.MaxContentSize)],
|
||||||
|
_window.OfficePaper));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnSendButtonPressed()
|
private void OnSendButtonPressed()
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ public sealed class AdminFaxEui : BaseEui
|
|||||||
}
|
}
|
||||||
case AdminFaxEuiMsg.Send sendData:
|
case AdminFaxEuiMsg.Send sendData:
|
||||||
{
|
{
|
||||||
var printout = new FaxPrintout(sendData.Content, sendData.Title, null, sendData.StampState,
|
var printout = new FaxPrintout(sendData.Content, sendData.Title, null, null, sendData.StampState,
|
||||||
new() { new StampDisplayInfo { StampedName = sendData.From, StampedColor = sendData.StampColor } });
|
new() { new StampDisplayInfo { StampedName = sendData.From, StampedColor = sendData.StampColor } });
|
||||||
_faxSystem.Receive(_entityManager.GetEntity(sendData.Target), printout);
|
_faxSystem.Receive(_entityManager.GetEntity(sendData.Target), printout);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ public static class FaxConstants
|
|||||||
|
|
||||||
public const string FaxNameData = "fax_data_name";
|
public const string FaxNameData = "fax_data_name";
|
||||||
public const string FaxPaperNameData = "fax_data_title";
|
public const string FaxPaperNameData = "fax_data_title";
|
||||||
|
public const string FaxPaperLabelData = "fax_data_label";
|
||||||
public const string FaxPaperPrototypeData = "fax_data_prototype";
|
public const string FaxPaperPrototypeData = "fax_data_prototype";
|
||||||
public const string FaxPaperContentData = "fax_data_content";
|
public const string FaxPaperContentData = "fax_data_content";
|
||||||
public const string FaxPaperStampStateData = "fax_data_stamp_state";
|
public const string FaxPaperStampStateData = "fax_data_stamp_state";
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using Content.Server.Chat.Managers;
|
|||||||
using Content.Server.DeviceNetwork;
|
using Content.Server.DeviceNetwork;
|
||||||
using Content.Server.DeviceNetwork.Components;
|
using Content.Server.DeviceNetwork.Components;
|
||||||
using Content.Server.DeviceNetwork.Systems;
|
using Content.Server.DeviceNetwork.Systems;
|
||||||
|
using Content.Server.Labels;
|
||||||
using Content.Server.Paper;
|
using Content.Server.Paper;
|
||||||
using Content.Server.Popups;
|
using Content.Server.Popups;
|
||||||
using Content.Server.Power.Components;
|
using Content.Server.Power.Components;
|
||||||
@@ -19,6 +20,7 @@ using Content.Shared.Fax;
|
|||||||
using Content.Shared.Fax.Systems;
|
using Content.Shared.Fax.Systems;
|
||||||
using Content.Shared.Fax.Components;
|
using Content.Shared.Fax.Components;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
|
using Content.Shared.Labels.Components;
|
||||||
using Content.Shared.Mobs.Components;
|
using Content.Shared.Mobs.Components;
|
||||||
using Content.Shared.Paper;
|
using Content.Shared.Paper;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
@@ -39,6 +41,7 @@ public sealed class FaxSystem : EntitySystem
|
|||||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||||
[Dependency] private readonly DeviceNetworkSystem _deviceNetworkSystem = default!;
|
[Dependency] private readonly DeviceNetworkSystem _deviceNetworkSystem = default!;
|
||||||
[Dependency] private readonly PaperSystem _paperSystem = default!;
|
[Dependency] private readonly PaperSystem _paperSystem = default!;
|
||||||
|
[Dependency] private readonly LabelSystem _labelSystem = default!;
|
||||||
[Dependency] private readonly SharedAudioSystem _audioSystem = default!;
|
[Dependency] private readonly SharedAudioSystem _audioSystem = default!;
|
||||||
[Dependency] private readonly ToolSystem _toolSystem = default!;
|
[Dependency] private readonly ToolSystem _toolSystem = default!;
|
||||||
[Dependency] private readonly QuickDialogSystem _quickDialog = default!;
|
[Dependency] private readonly QuickDialogSystem _quickDialog = default!;
|
||||||
@@ -240,7 +243,7 @@ public sealed class FaxSystem : EntitySystem
|
|||||||
}
|
}
|
||||||
|
|
||||||
_adminLogger.Add(LogType.Action, LogImpact.Low,
|
_adminLogger.Add(LogType.Action, LogImpact.Low,
|
||||||
$"{ToPrettyString(args.User):user} renamed {ToPrettyString(uid)} from \"{component.FaxName}\" to \"{newName}\"");
|
$"{ToPrettyString(args.User):user} renamed {ToPrettyString(uid):tool} from \"{component.FaxName}\" to \"{newName}\"");
|
||||||
component.FaxName = newName;
|
component.FaxName = newName;
|
||||||
_popupSystem.PopupEntity(Loc.GetString("fax-machine-popup-name-set"), uid);
|
_popupSystem.PopupEntity(Loc.GetString("fax-machine-popup-name-set"), uid);
|
||||||
UpdateUserInterface(uid, component);
|
UpdateUserInterface(uid, component);
|
||||||
@@ -292,11 +295,12 @@ public sealed class FaxSystem : EntitySystem
|
|||||||
!args.Data.TryGetValue(FaxConstants.FaxPaperContentData, out string? content))
|
!args.Data.TryGetValue(FaxConstants.FaxPaperContentData, out string? content))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
args.Data.TryGetValue(FaxConstants.FaxPaperLabelData, out string? label);
|
||||||
args.Data.TryGetValue(FaxConstants.FaxPaperStampStateData, out string? stampState);
|
args.Data.TryGetValue(FaxConstants.FaxPaperStampStateData, out string? stampState);
|
||||||
args.Data.TryGetValue(FaxConstants.FaxPaperStampedByData, out List<StampDisplayInfo>? stampedBy);
|
args.Data.TryGetValue(FaxConstants.FaxPaperStampedByData, out List<StampDisplayInfo>? stampedBy);
|
||||||
args.Data.TryGetValue(FaxConstants.FaxPaperPrototypeData, out string? prototypeId);
|
args.Data.TryGetValue(FaxConstants.FaxPaperPrototypeData, out string? prototypeId);
|
||||||
|
|
||||||
var printout = new FaxPrintout(content, name, prototypeId, stampState, stampedBy);
|
var printout = new FaxPrintout(content, name, label, prototypeId, stampState, stampedBy);
|
||||||
Receive(uid, printout, args.SenderAddress);
|
Receive(uid, printout, args.SenderAddress);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -311,6 +315,7 @@ public sealed class FaxSystem : EntitySystem
|
|||||||
|
|
||||||
private void OnFileButtonPressed(EntityUid uid, FaxMachineComponent component, FaxFileMessage args)
|
private void OnFileButtonPressed(EntityUid uid, FaxMachineComponent component, FaxFileMessage args)
|
||||||
{
|
{
|
||||||
|
args.Label = args.Label?[..Math.Min(args.Label.Length, FaxFileMessageValidation.MaxLabelSize)];
|
||||||
args.Content = args.Content[..Math.Min(args.Content.Length, FaxFileMessageValidation.MaxContentSize)];
|
args.Content = args.Content[..Math.Min(args.Content.Length, FaxFileMessageValidation.MaxContentSize)];
|
||||||
PrintFile(uid, component, args);
|
PrintFile(uid, component, args);
|
||||||
}
|
}
|
||||||
@@ -328,7 +333,7 @@ public sealed class FaxSystem : EntitySystem
|
|||||||
if (HasComp<MobStateComponent>(component.PaperSlot.Item))
|
if (HasComp<MobStateComponent>(component.PaperSlot.Item))
|
||||||
_faxecute.Faxecute(uid, component); /// when button pressed it will hurt the mob.
|
_faxecute.Faxecute(uid, component); /// when button pressed it will hurt the mob.
|
||||||
else
|
else
|
||||||
Send(uid, component, args.Actor);
|
Send(uid, component, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnRefreshButtonPressed(EntityUid uid, FaxMachineComponent component, FaxRefreshMessage args)
|
private void OnRefreshButtonPressed(EntityUid uid, FaxMachineComponent component, FaxRefreshMessage args)
|
||||||
@@ -425,16 +430,20 @@ public sealed class FaxSystem : EntitySystem
|
|||||||
else
|
else
|
||||||
prototype = DefaultPaperPrototypeId;
|
prototype = DefaultPaperPrototypeId;
|
||||||
|
|
||||||
var name = Loc.GetString("fax-machine-printed-paper-name");
|
var name = Loc.GetString("fax-machine-printed-paper-name");
|
||||||
|
|
||||||
var printout = new FaxPrintout(args.Content, name, prototype);
|
var printout = new FaxPrintout(args.Content, name, args.Label, prototype);
|
||||||
component.PrintingQueue.Enqueue(printout);
|
component.PrintingQueue.Enqueue(printout);
|
||||||
component.SendTimeoutRemaining += component.SendTimeout;
|
component.SendTimeoutRemaining += component.SendTimeout;
|
||||||
|
|
||||||
UpdateUserInterface(uid, component);
|
UpdateUserInterface(uid, component);
|
||||||
|
|
||||||
|
// Unfortunately, since a paper entity does not yet exist, we have to emulate what LabelSystem will do.
|
||||||
|
var nameWithLabel = (args.Label is { } label) ? $"{name} ({label})" : name;
|
||||||
_adminLogger.Add(LogType.Action, LogImpact.Low,
|
_adminLogger.Add(LogType.Action, LogImpact.Low,
|
||||||
$"{ToPrettyString(args.Actor):actor} added print job to {ToPrettyString(uid):tool} with text: {args.Content}");
|
$"{ToPrettyString(args.Actor):actor} " +
|
||||||
|
$"added print job to \"{component.FaxName}\" {ToPrettyString(uid):tool} " +
|
||||||
|
$"of {nameWithLabel}: {args.Content}");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -454,9 +463,12 @@ public sealed class FaxSystem : EntitySystem
|
|||||||
!TryComp<PaperComponent>(sendEntity, out var paper))
|
!TryComp<PaperComponent>(sendEntity, out var paper))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
TryComp<LabelComponent>(sendEntity, out var labelComponent);
|
||||||
|
|
||||||
// TODO: See comment in 'Send()' about not being able to copy whole entities
|
// TODO: See comment in 'Send()' about not being able to copy whole entities
|
||||||
var printout = new FaxPrintout(paper.Content,
|
var printout = new FaxPrintout(paper.Content,
|
||||||
metadata.EntityName,
|
labelComponent?.OriginalName ?? metadata.EntityName,
|
||||||
|
labelComponent?.CurrentLabel,
|
||||||
metadata.EntityPrototype?.ID ?? DefaultPaperPrototypeId,
|
metadata.EntityPrototype?.ID ?? DefaultPaperPrototypeId,
|
||||||
paper.StampState,
|
paper.StampState,
|
||||||
paper.StampedBy);
|
paper.StampedBy);
|
||||||
@@ -470,14 +482,16 @@ public sealed class FaxSystem : EntitySystem
|
|||||||
UpdateUserInterface(uid, component);
|
UpdateUserInterface(uid, component);
|
||||||
|
|
||||||
_adminLogger.Add(LogType.Action, LogImpact.Low,
|
_adminLogger.Add(LogType.Action, LogImpact.Low,
|
||||||
$"{ToPrettyString(args.Actor):actor} added copy job to {ToPrettyString(uid):tool} with text: {ToPrettyString(component.PaperSlot.Item):subject}");
|
$"{ToPrettyString(args.Actor):actor} " +
|
||||||
|
$"added copy job to \"{component.FaxName}\" {ToPrettyString(uid):tool} " +
|
||||||
|
$"of {ToPrettyString(sendEntity):subject}: {printout.Content}");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sends message to addressee if paper is set and a known fax is selected
|
/// Sends message to addressee if paper is set and a known fax is selected
|
||||||
/// A timeout is set after sending, which is shared by the copy button.
|
/// A timeout is set after sending, which is shared by the copy button.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Send(EntityUid uid, FaxMachineComponent? component = null, EntityUid? sender = null)
|
public void Send(EntityUid uid, FaxMachineComponent? component, FaxSendMessage args)
|
||||||
{
|
{
|
||||||
if (!Resolve(uid, ref component))
|
if (!Resolve(uid, ref component))
|
||||||
return;
|
return;
|
||||||
@@ -496,10 +510,13 @@ public sealed class FaxSystem : EntitySystem
|
|||||||
!TryComp<PaperComponent>(sendEntity, out var paper))
|
!TryComp<PaperComponent>(sendEntity, out var paper))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
TryComp<LabelComponent>(sendEntity, out var labelComponent);
|
||||||
|
|
||||||
var payload = new NetworkPayload()
|
var payload = new NetworkPayload()
|
||||||
{
|
{
|
||||||
{ DeviceNetworkConstants.Command, FaxConstants.FaxPrintCommand },
|
{ DeviceNetworkConstants.Command, FaxConstants.FaxPrintCommand },
|
||||||
{ FaxConstants.FaxPaperNameData, metadata.EntityName },
|
{ FaxConstants.FaxPaperNameData, labelComponent?.OriginalName ?? metadata.EntityName },
|
||||||
|
{ FaxConstants.FaxPaperLabelData, labelComponent?.CurrentLabel },
|
||||||
{ FaxConstants.FaxPaperContentData, paper.Content },
|
{ FaxConstants.FaxPaperContentData, paper.Content },
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -520,7 +537,11 @@ public sealed class FaxSystem : EntitySystem
|
|||||||
|
|
||||||
_deviceNetworkSystem.QueuePacket(uid, component.DestinationFaxAddress, payload);
|
_deviceNetworkSystem.QueuePacket(uid, component.DestinationFaxAddress, payload);
|
||||||
|
|
||||||
_adminLogger.Add(LogType.Action, LogImpact.Low, $"{(sender != null ? ToPrettyString(sender.Value) : "Unknown"):user} sent fax from \"{component.FaxName}\" {ToPrettyString(uid)} to {faxName} ({component.DestinationFaxAddress}): {paper.Content}");
|
_adminLogger.Add(LogType.Action, LogImpact.Low,
|
||||||
|
$"{ToPrettyString(args.Actor):actor} " +
|
||||||
|
$"sent fax from \"{component.FaxName}\" {ToPrettyString(uid):tool} " +
|
||||||
|
$"to \"{faxName}\" ({component.DestinationFaxAddress}) " +
|
||||||
|
$"of {ToPrettyString(sendEntity):subject}: {paper.Content}");
|
||||||
|
|
||||||
component.SendTimeoutRemaining += component.SendTimeout;
|
component.SendTimeoutRemaining += component.SendTimeout;
|
||||||
|
|
||||||
@@ -576,7 +597,13 @@ public sealed class FaxSystem : EntitySystem
|
|||||||
}
|
}
|
||||||
|
|
||||||
_metaData.SetEntityName(printed, printout.Name);
|
_metaData.SetEntityName(printed, printout.Name);
|
||||||
_adminLogger.Add(LogType.Action, LogImpact.Low, $"\"{component.FaxName}\" {ToPrettyString(uid)} printed {ToPrettyString(printed)}: {printout.Content}");
|
|
||||||
|
if (printout.Label is { } label)
|
||||||
|
{
|
||||||
|
_labelSystem.Label(printed, label);
|
||||||
|
}
|
||||||
|
|
||||||
|
_adminLogger.Add(LogType.Action, LogImpact.Low, $"\"{component.FaxName}\" {ToPrettyString(uid):tool} printed {ToPrettyString(printed):subject}: {printout.Content}");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void NotifyAdmins(string faxName)
|
private void NotifyAdmins(string faxName)
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ namespace Content.Server.Nuke
|
|||||||
paperContent,
|
paperContent,
|
||||||
Loc.GetString("nuke-codes-fax-paper-name"),
|
Loc.GetString("nuke-codes-fax-paper-name"),
|
||||||
null,
|
null,
|
||||||
|
null,
|
||||||
"paper_stamp-centcom",
|
"paper_stamp-centcom",
|
||||||
new List<StampDisplayInfo>
|
new List<StampDisplayInfo>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -135,6 +135,9 @@ public sealed partial class FaxPrintout
|
|||||||
[DataField(required: true)]
|
[DataField(required: true)]
|
||||||
public string Name { get; private set; } = default!;
|
public string Name { get; private set; } = default!;
|
||||||
|
|
||||||
|
[DataField]
|
||||||
|
public string? Label { get; private set; }
|
||||||
|
|
||||||
[DataField(required: true)]
|
[DataField(required: true)]
|
||||||
public string Content { get; private set; } = default!;
|
public string Content { get; private set; } = default!;
|
||||||
|
|
||||||
@@ -151,10 +154,11 @@ public sealed partial class FaxPrintout
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public FaxPrintout(string content, string name, string? prototypeId = null, string? stampState = null, List<StampDisplayInfo>? stampedBy = null)
|
public FaxPrintout(string content, string name, string? label = null, string? prototypeId = null, string? stampState = null, List<StampDisplayInfo>? stampedBy = null)
|
||||||
{
|
{
|
||||||
Content = content;
|
Content = content;
|
||||||
Name = name;
|
Name = name;
|
||||||
|
Label = label;
|
||||||
PrototypeId = prototypeId ?? "";
|
PrototypeId = prototypeId ?? "";
|
||||||
StampState = stampState;
|
StampState = stampState;
|
||||||
StampedBy = stampedBy ?? new List<StampDisplayInfo>();
|
StampedBy = stampedBy ?? new List<StampDisplayInfo>();
|
||||||
|
|||||||
@@ -37,11 +37,13 @@ public sealed class FaxUiState : BoundUserInterfaceState
|
|||||||
[Serializable, NetSerializable]
|
[Serializable, NetSerializable]
|
||||||
public sealed class FaxFileMessage : BoundUserInterfaceMessage
|
public sealed class FaxFileMessage : BoundUserInterfaceMessage
|
||||||
{
|
{
|
||||||
|
public string? Label;
|
||||||
public string Content;
|
public string Content;
|
||||||
public bool OfficePaper;
|
public bool OfficePaper;
|
||||||
|
|
||||||
public FaxFileMessage(string content, bool officePaper)
|
public FaxFileMessage(string? label, string content, bool officePaper)
|
||||||
{
|
{
|
||||||
|
Label = label;
|
||||||
Content = content;
|
Content = content;
|
||||||
OfficePaper = officePaper;
|
OfficePaper = officePaper;
|
||||||
}
|
}
|
||||||
@@ -49,6 +51,7 @@ public sealed class FaxFileMessage : BoundUserInterfaceMessage
|
|||||||
|
|
||||||
public static class FaxFileMessageValidation
|
public static class FaxFileMessageValidation
|
||||||
{
|
{
|
||||||
|
public const int MaxLabelSize = 50; // parity with Content.Server.Labels.Components.HandLabelerComponent.MaxLabelChars
|
||||||
public const int MaxContentSize = 10000;
|
public const int MaxContentSize = 10000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user