using System; using System.Collections.Generic; using System.Linq; using Content.Server.Light.EntitySystems; using Content.Server.Storage.Components; using Content.Shared.Light; using Content.Shared.Popups; using Content.Shared.Sound; using Robust.Shared.Audio; using Robust.Shared.Containers; using Robust.Shared.GameObjects; using Robust.Shared.Localization; using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; using Robust.Shared.ViewVariables; namespace Content.Server.Light.Components { /// /// Device that allows user to quikly change bulbs in /// Can be reloaded by new light tubes or light bulbs /// [RegisterComponent] public class LightReplacerComponent : Component { public override string Name => "LightReplacer"; [DataField("sound")] private SoundSpecifier _sound = new SoundPathSpecifier("/Audio/Weapons/click.ogg"); // bulbs that were inside light replacer when it spawned [DataField("contents")] private List _contents = new(); // bulbs that were inserted inside light replacer [ViewVariables] private IContainer _insertedBulbs = default!; protected override void Initialize() { base.Initialize(); _insertedBulbs = ContainerHelpers.EnsureContainer(Owner, "light_replacer_storage"); } public bool TryReplaceBulb(PoweredLightComponent fixture, IEntity? user = null) { // check if light bulb is broken or missing var lightSystem = EntitySystem.Get(); var fixtureBulbUid = lightSystem.GetBulb(fixture.Owner.Uid, fixture); if (fixtureBulbUid == null) return false; if (!Owner.EntityManager.TryGetComponent(fixtureBulbUid.Value, out LightBulbComponent? fixtureBulb)) return false; if (fixtureBulb.State == LightBulbState.Normal) return false; // try get first inserted bulb of the same type as targeted light fixtutre var bulb = _insertedBulbs.ContainedEntities.FirstOrDefault( (e) => e.GetComponentOrNull()?.Type == fixture.BulbType); // found bulb in inserted storage if (bulb != null) { // try to remove it var hasRemoved = _insertedBulbs.Remove(bulb); if (!hasRemoved) return false; } // try to create new instance of bulb from LightReplacerEntity else { var bulbEnt = _contents.FirstOrDefault((e) => e.Type == fixture.BulbType && e.Amount > 0); // found right bulb, let's spawn it if (bulbEnt != null) { bulb = Owner.EntityManager.SpawnEntity(bulbEnt.PrototypeName, Owner.Transform.Coordinates); bulbEnt.Amount--; } // not found any light bulbs else { if (user != null) { var msg = Loc.GetString("comp-light-replacer-missing-light", ("light-replacer", Owner)); user.PopupMessage(msg); } return false; } } // insert it into fixture var wasReplaced = lightSystem.ReplaceBulb(fixture.Owner.Uid, bulb.Uid, fixture); if (wasReplaced) { SoundSystem.Play(Filter.Pvs(Owner), _sound.GetSound(), Owner, AudioParams.Default.WithVolume(-4f)); } return wasReplaced; } public bool TryInsertBulb(LightBulbComponent bulb, IEntity? user = null, bool showTooltip = false) { // only normal lights can be inserted inside light replacer if (bulb.State != LightBulbState.Normal) { if (showTooltip && user != null) { var msg = Loc.GetString("comp-light-replacer-insert-broken-light"); user.PopupMessage(msg); } return false; } // try insert light and show message var hasInsert = _insertedBulbs.Insert(bulb.Owner); if (hasInsert && showTooltip && user != null) { var msg = Loc.GetString("comp-light-replacer-insert-light", ("light-replacer", Owner), ("bulb", bulb.Owner)); user.PopupMessage(msg); } return hasInsert; } public bool TryInsertBulb(ServerStorageComponent storage, IEntity? user = null) { if (storage.StoredEntities == null) return false; var insertedBulbs = 0; var storagedEnts = storage.StoredEntities.ToArray(); foreach (var ent in storagedEnts) { if (ent.TryGetComponent(out LightBulbComponent? bulb)) { if (TryInsertBulb(bulb)) insertedBulbs++; } } // show some message if success if (insertedBulbs > 0 && user != null) { var msg = Loc.GetString("comp-light-replacer-refill-from-storage", ("light-replacer", Owner)); user.PopupMessage(msg); } return insertedBulbs > 0; } [Serializable] [DataDefinition] public class LightReplacerEntity { [DataField("name", customTypeSerializer: typeof(PrototypeIdSerializer))] public string? PrototypeName; [DataField("amount")] public int Amount; [DataField("type")] public LightBulbType Type; } } }