| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258 |
- using System.Linq;
- using Content.Shared.Administration.Logs;
- using Content.Shared.UserInterface;
- using Content.Shared.Database;
- using Content.Shared.Examine;
- using Content.Shared.Interaction;
- using Content.Shared.Popups;
- using Content.Shared.Tag;
- using Robust.Shared.Player;
- using Robust.Shared.Audio.Systems;
- using static Content.Shared.Paper.PaperComponent;
- namespace Content.Shared.Paper;
- public sealed class PaperSystem : EntitySystem
- {
- [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
- [Dependency] private readonly SharedAppearanceSystem _appearance = default!;
- [Dependency] private readonly SharedInteractionSystem _interaction = default!;
- [Dependency] private readonly SharedPopupSystem _popupSystem = default!;
- [Dependency] private readonly TagSystem _tagSystem = default!;
- [Dependency] private readonly SharedUserInterfaceSystem _uiSystem = default!;
- [Dependency] private readonly MetaDataSystem _metaSystem = default!;
- [Dependency] private readonly SharedAudioSystem _audio = default!;
- public override void Initialize()
- {
- base.Initialize();
- SubscribeLocalEvent<PaperComponent, MapInitEvent>(OnMapInit);
- SubscribeLocalEvent<PaperComponent, ComponentInit>(OnInit);
- SubscribeLocalEvent<PaperComponent, BeforeActivatableUIOpenEvent>(BeforeUIOpen);
- SubscribeLocalEvent<PaperComponent, ExaminedEvent>(OnExamined);
- SubscribeLocalEvent<PaperComponent, InteractUsingEvent>(OnInteractUsing);
- SubscribeLocalEvent<PaperComponent, PaperInputTextMessage>(OnInputTextMessage);
- SubscribeLocalEvent<ActivateOnPaperOpenedComponent, PaperWriteEvent>(OnPaperWrite);
- }
- private void OnMapInit(Entity<PaperComponent> entity, ref MapInitEvent args)
- {
- if (!string.IsNullOrEmpty(entity.Comp.Content))
- {
- SetContent(entity, Loc.GetString(entity.Comp.Content));
- }
- }
- private void OnInit(Entity<PaperComponent> entity, ref ComponentInit args)
- {
- entity.Comp.Mode = PaperAction.Read;
- UpdateUserInterface(entity);
- if (TryComp<AppearanceComponent>(entity, out var appearance))
- {
- if (entity.Comp.Content != "")
- _appearance.SetData(entity, PaperVisuals.Status, PaperStatus.Written, appearance);
- if (entity.Comp.StampState != null)
- _appearance.SetData(entity, PaperVisuals.Stamp, entity.Comp.StampState, appearance);
- }
- }
- private void BeforeUIOpen(Entity<PaperComponent> entity, ref BeforeActivatableUIOpenEvent args)
- {
- entity.Comp.Mode = PaperAction.Read;
- UpdateUserInterface(entity);
- }
- private void OnExamined(Entity<PaperComponent> entity, ref ExaminedEvent args)
- {
- if (!args.IsInDetailsRange)
- return;
- using (args.PushGroup(nameof(PaperComponent)))
- {
- if (entity.Comp.Content != "")
- {
- args.PushMarkup(
- Loc.GetString(
- "paper-component-examine-detail-has-words",
- ("paper", entity)
- )
- );
- }
- if (entity.Comp.StampedBy.Count > 0)
- {
- var commaSeparated =
- string.Join(", ", entity.Comp.StampedBy.Select(s => Loc.GetString(s.StampedName)));
- args.PushMarkup(
- Loc.GetString(
- "paper-component-examine-detail-stamped-by",
- ("paper", entity),
- ("stamps", commaSeparated))
- );
- }
- }
- }
- private void OnInteractUsing(Entity<PaperComponent> entity, ref InteractUsingEvent args)
- {
- // only allow editing if there are no stamps or when using a cyberpen
- var editable = entity.Comp.StampedBy.Count == 0 || _tagSystem.HasTag(args.Used, "WriteIgnoreStamps");
- if (_tagSystem.HasTag(args.Used, "Write"))
- {
- if (editable)
- {
- if (entity.Comp.EditingDisabled)
- {
- var paperEditingDisabledMessage = Loc.GetString("paper-tamper-proof-modified-message");
- _popupSystem.PopupEntity(paperEditingDisabledMessage, entity, args.User);
- args.Handled = true;
- return;
- }
- var ev = new PaperWriteAttemptEvent(entity.Owner);
- RaiseLocalEvent(args.User, ref ev);
- if (ev.Cancelled)
- {
- if (ev.FailReason is not null)
- {
- var fileWriteMessage = Loc.GetString(ev.FailReason);
- _popupSystem.PopupClient(fileWriteMessage, entity.Owner, args.User);
- }
- args.Handled = true;
- return;
- }
- var writeEvent = new PaperWriteEvent(args.User, entity);
- RaiseLocalEvent(args.Used, ref writeEvent);
- entity.Comp.Mode = PaperAction.Write;
- _uiSystem.OpenUi(entity.Owner, PaperUiKey.Key, args.User);
- UpdateUserInterface(entity);
- }
- args.Handled = true;
- return;
- }
- // If a stamp, attempt to stamp paper
- if (TryComp<StampComponent>(args.Used, out var stampComp) && TryStamp(entity, GetStampInfo(stampComp), stampComp.StampState))
- {
- // successfully stamped, play popup
- var stampPaperOtherMessage = Loc.GetString("paper-component-action-stamp-paper-other",
- ("user", args.User),
- ("target", args.Target),
- ("stamp", args.Used));
- _popupSystem.PopupEntity(stampPaperOtherMessage, args.User, Filter.PvsExcept(args.User, entityManager: EntityManager), true);
- var stampPaperSelfMessage = Loc.GetString("paper-component-action-stamp-paper-self",
- ("target", args.Target),
- ("stamp", args.Used));
- _popupSystem.PopupClient(stampPaperSelfMessage, args.User, args.User);
- _audio.PlayPredicted(stampComp.Sound, entity, args.User);
- UpdateUserInterface(entity);
- }
- }
- private static StampDisplayInfo GetStampInfo(StampComponent stamp)
- {
- return new StampDisplayInfo
- {
- StampedName = stamp.StampedName,
- StampedColor = stamp.StampedColor
- };
- }
- private void OnInputTextMessage(Entity<PaperComponent> entity, ref PaperInputTextMessage args)
- {
- var ev = new PaperWriteAttemptEvent(entity.Owner);
- RaiseLocalEvent(args.Actor, ref ev);
- if (ev.Cancelled)
- return;
- if (args.Text.Length <= entity.Comp.ContentSize)
- {
- SetContent(entity, args.Text);
- if (TryComp<AppearanceComponent>(entity, out var appearance))
- _appearance.SetData(entity, PaperVisuals.Status, PaperStatus.Written, appearance);
- if (TryComp(entity, out MetaDataComponent? meta))
- _metaSystem.SetEntityDescription(entity, "", meta);
- _adminLogger.Add(LogType.Chat,
- LogImpact.Low,
- $"{ToPrettyString(args.Actor):player} has written on {ToPrettyString(entity):entity} the following text: {args.Text}");
- _audio.PlayPvs(entity.Comp.Sound, entity);
- }
- entity.Comp.Mode = PaperAction.Read;
- UpdateUserInterface(entity);
- }
- private void OnPaperWrite(Entity<ActivateOnPaperOpenedComponent> entity, ref PaperWriteEvent args)
- {
- _interaction.UseInHandInteraction(args.User, entity);
- }
- /// <summary>
- /// Accepts the name and state to be stamped onto the paper, returns true if successful.
- /// </summary>
- public bool TryStamp(Entity<PaperComponent> entity, StampDisplayInfo stampInfo, string spriteStampState)
- {
- if (!entity.Comp.StampedBy.Contains(stampInfo))
- {
- entity.Comp.StampedBy.Add(stampInfo);
- Dirty(entity);
- if (entity.Comp.StampState == null && TryComp<AppearanceComponent>(entity, out var appearance))
- {
- entity.Comp.StampState = spriteStampState;
- // Would be nice to be able to display multiple sprites on the paper
- // but most of the existing images overlap
- _appearance.SetData(entity, PaperVisuals.Stamp, entity.Comp.StampState, appearance);
- }
- }
- return true;
- }
- public void SetContent(Entity<PaperComponent> entity, string content)
- {
- entity.Comp.Content = content;
- Dirty(entity);
- UpdateUserInterface(entity);
- if (!TryComp<AppearanceComponent>(entity, out var appearance))
- return;
- var status = string.IsNullOrWhiteSpace(content)
- ? PaperStatus.Blank
- : PaperStatus.Written;
- _appearance.SetData(entity, PaperVisuals.Status, status, appearance);
- }
- private void UpdateUserInterface(Entity<PaperComponent> entity)
- {
- _uiSystem.SetUiState(entity.Owner, PaperUiKey.Key, new PaperBoundUserInterfaceState(entity.Comp.Content, entity.Comp.StampedBy, entity.Comp.Mode));
- }
- }
- /// <summary>
- /// Event fired when using a pen on paper, opening the UI.
- /// </summary>
- [ByRefEvent]
- public record struct PaperWriteEvent(EntityUid User, EntityUid Paper);
- /// <summary>
- /// Cancellable event for attempting to write on a piece of paper.
- /// </summary>
- /// <param name="paper">The paper that the writing will take place on.</param>
- [ByRefEvent]
- public record struct PaperWriteAttemptEvent(EntityUid Paper, string? FailReason = null, bool Cancelled = false);
|