using Content.Shared.EntityTable;
using Content.Shared.Examine;
using Content.Shared.Flash;
using Content.Shared.Hands.EntitySystems;
using Content.Shared.IdentityManagement;
using Robust.Shared.Network;
using Robust.Shared.Utility;
namespace Content.Shared.Photography;
///
/// Handles everything related to photography.
///
public sealed partial class PhotographySystem : EntitySystem
{
[Dependency] private ExamineSystemShared _examine = default!;
[Dependency] private SharedHandsSystem _hands = default!;
[Dependency] private EntityTableSystem _tables = default!;
[Dependency] private INetManager _net = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent(OnExamined);
SubscribeLocalEvent(OnFlashActivated);
}
private void OnExamined(Entity ent, ref ExaminedEvent args)
{
if (!args.IsInDetailsRange)
return;
using (args.PushGroup(nameof(PhotographComponent)))
{
if (string.IsNullOrEmpty(ent.Comp.NameText))
args.PushText(Loc.GetString("photograph-name-text-empty"));
else
args.PushText(ent.Comp.NameText);
if (ent.Comp.Description != null)
// TODO: For some weird reason ExamineSystem is adding a new line at the end of message we are pushing with each examine.
// I'm not soaping this PR even more, so for now I'll just bandaid that by sending a clone to prevent it from getting modified.
args.PushMessage(new FormattedMessage(ent.Comp.Description));
}
}
// The flash system is handling charges and all interactions, we just print the picture afterwards.
private void OnFlashActivated(Entity ent, ref AfterFlashActivatedEvent args)
{
TakePicture(ent, args.Target, args.User);
}
///
/// Processes entity aimed at with a camera and prints a picture of it.
/// TODO: This is basically a placeholder mechanic for a more elaborate photography system.
/// However, this will need major refactoring to be possible. See
/// https://github.com/space-wizards/docs/pull/307 and
/// https://github.com/space-wizards/space-station-14/pull/43327
/// for details.
///
public void TakePicture(Entity camera, EntityUid? target, EntityUid? user)
{
if (_net.IsClient)
return; // Can't interact with predictively spawned entities yet.
var tableResult = _tables.GetSpawns(camera.Comp.Photographs);
var coords = Transform(camera).Coordinates;
FormattedMessage? description = null;
string? nameText = null;
if (target != null)
{
description = _examine.GetExamineText(target.Value, user);
// Get the full string now instead of indexing it later because we need the entity to know if it uses a proper noun or not.
nameText = Loc.GetString("photograph-name-text", ("entity", Identity.Entity(target.Value, EntityManager)));
// We don't want photographs to contain the descriptions of other photographs, because that makes entities with, in theory, infinite descriptions.
if (HasComp(target.Value))
{
description = null;
nameText = Loc.GetString("photograph-name-text-photograph");
}
}
foreach (var prototype in tableResult)
{
// we generate an individual photograph (there should be only one tough)
var spawned = Spawn(prototype, coords);
var photoComp = EnsureComp(spawned);
photoComp.NameText = nameText;
photoComp.Description = description;
Dirty(spawned, photoComp);
_hands.PickupOrDrop(user, spawned, dropNear: true);
}
}
}