// © SUNRISE, An EULA/CLA with a hosting restriction, full text: https://github.com/space-sunrise/space-station-14/blob/master/CLA.txt;
using Content.Shared._Sunrise.Razor;
using Content.Shared.DoAfter;
using Content.Shared.Humanoid;
using Content.Shared.Humanoid.Markings;
using Content.Shared.Interaction;
using Content.Shared._Sunrise.Razor;
using Content.Shared.UserInterface;
using Robust.Shared.Serialization;
namespace Content.Shared._Sunrise.Razor;
///
/// Система для электробритвы - копия ножниц с вайлдберрис. Бритва не может менять цвет волос!
///
public abstract class SharedRazorSystem : EntitySystem
{
[Dependency] private readonly SharedInteractionSystem _interaction = default!;
[Dependency] private readonly SharedUserInterfaceSystem _uiSystem = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent(OnRazorInteract);
SubscribeLocalEvent(OnBeforeUIOpen);
SubscribeLocalEvent(OnAttemptOpenUI);
SubscribeLocalEvent(OnMirrorRangeCheck);
}
private void OnRazorInteract(Entity mirror, ref AfterInteractEvent args)
{
if (!args.CanReach || args.Target == null)
return;
UpdateInterface(mirror, args.Target.Value, mirror);
_uiSystem.TryOpenUi(mirror.Owner, RazorUiKey.Key, args.User);
}
private void OnMirrorRangeCheck(EntityUid uid, RazorComponent component, ref BoundUserInterfaceCheckRangeEvent args)
{
if (args.Result == BoundUserInterfaceRangeResult.Fail)
return;
if (component.Target == null || !Exists(component.Target))
{
component.Target = null;
args.Result = BoundUserInterfaceRangeResult.Fail;
return;
}
if (!_interaction.InRangeUnobstructed(component.Target.Value, uid))
args.Result = BoundUserInterfaceRangeResult.Fail;
}
private void OnAttemptOpenUI(EntityUid uid, RazorComponent component, ref ActivatableUIOpenAttemptEvent args)
{
var user = component.Target ?? args.User;
if (!HasComp(user))
args.Cancel();
}
private void OnBeforeUIOpen(Entity ent, ref BeforeActivatableUIOpenEvent args)
{
UpdateInterface(ent, args.User, ent);
}
protected void UpdateInterface(EntityUid mirrorUid, EntityUid targetUid, RazorComponent component)
{
if (!TryComp(targetUid, out var humanoid))
return;
component.Target ??= targetUid;
var hair = humanoid.MarkingSet.TryGetCategory(MarkingCategories.Hair, out var hairMarkings)
? new List(hairMarkings)
: [];
var facialHair = humanoid.MarkingSet.TryGetCategory(MarkingCategories.FacialHair, out var facialHairMarkings)
? new List(facialHairMarkings)
: [];
var state = new RazorUiState(
humanoid.Species,
hair,
humanoid.MarkingSet.PointsLeft(MarkingCategories.Hair) + hair.Count,
facialHair,
humanoid.MarkingSet.PointsLeft(MarkingCategories.FacialHair) + facialHair.Count);
// TODO: Component states
component.Target = targetUid;
_uiSystem.SetUiState(mirrorUid, RazorUiKey.Key, state);
Dirty(mirrorUid, component);
}
}
[Serializable, NetSerializable]
public enum RazorUiKey : byte
{
Key,
}
[Serializable, NetSerializable]
public enum RazorCategory : byte
{
Hair,
FacialHair,
}
[Serializable, NetSerializable]
public sealed class RazorSelectMessage(RazorCategory category, string marking, int slot) : BoundUserInterfaceMessage
{
public RazorCategory Category { get; } = category;
public string Marking { get; } = marking;
public int Slot { get; } = slot;
}
[Serializable, NetSerializable]
public sealed class RazorRemoveSlotMessage(RazorCategory category, int slot) : BoundUserInterfaceMessage
{
public RazorCategory Category { get; } = category;
public int Slot { get; } = slot;
}
[Serializable, NetSerializable]
public sealed class RazorSelectSlotMessage(RazorCategory category, int slot) : BoundUserInterfaceMessage
{
public RazorCategory Category { get; } = category;
public int Slot { get; } = slot;
}
[Serializable, NetSerializable]
public sealed class RazorAddSlotMessage(RazorCategory category) : BoundUserInterfaceMessage
{
public RazorCategory Category { get; } = category;
}
[Serializable, NetSerializable]
public sealed class RazorUiState(
string species,
List hair,
int hairSlotTotal,
List facialHair,
int facialHairSlotTotal)
: BoundUserInterfaceState
{
public NetEntity Target;
public string Species = species;
public List Hair = hair;
public int HairSlotTotal = hairSlotTotal;
public List FacialHair = facialHair;
public int FacialHairSlotTotal = facialHairSlotTotal;
}
[Serializable, NetSerializable]
public sealed partial class RazorRemoveSlotDoAfterEvent : DoAfterEvent
{
public override DoAfterEvent Clone()
{
return this;
}
public RazorCategory Category;
public int Slot;
}
[Serializable, NetSerializable]
public sealed partial class RazorAddSlotDoAfterEvent : DoAfterEvent
{
public override DoAfterEvent Clone()
{
return this;
}
public RazorCategory Category;
}
[Serializable, NetSerializable]
public sealed partial class RazorSelectDoAfterEvent : DoAfterEvent
{
public RazorCategory Category;
public int Slot;
public string Marking = string.Empty;
public override DoAfterEvent Clone()
{
return this;
}
}