using Content.Server.Administration.Logs; using Content.Server.Hands.Systems; using Content.Shared.Database; using Content.Shared.Examine; using Content.Shared.Interaction.Events; using Content.Shared.Item; using Content.Shared.Whitelist; using Robust.Server.Audio; using Robust.Shared.Map.Components; using Robust.Shared.Physics.Components; using Robust.Shared.Prototypes; using Robust.Shared.Random; namespace Content.Server.Holiday.Christmas; /// /// This handles granting players their gift. /// public sealed class RandomGiftSystem : EntitySystem { [Dependency] private readonly AudioSystem _audio = default!; [Dependency] private readonly HandsSystem _hands = default!; [Dependency] private readonly IComponentFactory _componentFactory = default!; [Dependency] private readonly IPrototypeManager _prototype = default!; [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly IAdminLogManager _adminLogger = default!; [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; [Dependency] private readonly SharedTransformSystem _transform = default!; private readonly List _possibleGiftsSafe = new(); private readonly List _possibleGiftsUnsafe = new(); /// public override void Initialize() { SubscribeLocalEvent(OnPrototypesReloaded); SubscribeLocalEvent(OnGiftMapInit); SubscribeLocalEvent(OnUseInHand); SubscribeLocalEvent(OnExamined); BuildIndex(); } private void OnExamined(EntityUid uid, RandomGiftComponent component, ExaminedEvent args) { if (_whitelistSystem.IsWhitelistFail(component.ContentsViewers, args.Examiner) || component.SelectedEntity is null) return; var name = _prototype.Index(component.SelectedEntity).Name; args.PushText(Loc.GetString("gift-packin-contains", ("name", name))); } private void OnUseInHand(EntityUid uid, RandomGiftComponent component, UseInHandEvent args) { if (args.Handled) return; if (component.SelectedEntity is null) return; var coords = Transform(args.User).Coordinates; var handsEnt = Spawn(component.SelectedEntity, coords); _adminLogger.Add(LogType.EntitySpawn, LogImpact.Low, $"{ToPrettyString(args.User)} used {ToPrettyString(uid)} which spawned {ToPrettyString(handsEnt)}"); if (component.Wrapper is not null) Spawn(component.Wrapper, coords); _audio.PlayPvs(component.Sound, args.User); // Don't delete the entity in the event bus, so we queue it for deletion. // We need the free hand for the new item, so we send it to nullspace. _transform.DetachEntity(uid, Transform(uid)); QueueDel(uid); _hands.PickupOrDrop(args.User, handsEnt); args.Handled = true; } private void OnGiftMapInit(EntityUid uid, RandomGiftComponent component, MapInitEvent args) { if (component.InsaneMode) component.SelectedEntity = _random.Pick(_possibleGiftsUnsafe); else component.SelectedEntity = _random.Pick(_possibleGiftsSafe); } private void OnPrototypesReloaded(PrototypesReloadedEventArgs obj) { if (obj.WasModified()) BuildIndex(); } private void BuildIndex() { _possibleGiftsSafe.Clear(); _possibleGiftsUnsafe.Clear(); var itemCompName = _componentFactory.GetComponentName(typeof(ItemComponent)); var mapGridCompName = _componentFactory.GetComponentName(typeof(MapGridComponent)); var physicsCompName = _componentFactory.GetComponentName(typeof(PhysicsComponent)); foreach (var proto in _prototype.EnumeratePrototypes()) { if (proto.Abstract || proto.HideSpawnMenu || proto.Components.ContainsKey(mapGridCompName) || !proto.Components.ContainsKey(physicsCompName)) continue; _possibleGiftsUnsafe.Add(proto.ID); if (!proto.Components.ContainsKey(itemCompName)) continue; _possibleGiftsSafe.Add(proto.ID); } } }