From 2cb35fab3c52a3eda8b7dfb0b4e0914cfedfb26c Mon Sep 17 00:00:00 2001 From: Alex Evgrashin Date: Thu, 28 Oct 2021 05:36:09 +0300 Subject: [PATCH] Fix light replacer and move it to ECS (#5053) * Fixed broken replacer prototype * Light replacer ECS --- .../Components/LightReplacerComponent.cs | 143 ++----------- .../EntitySystems/LightReplacerSystem.cs | 195 +++++++++++++++++- .../Entities/Objects/Tools/light_replacer.yml | 4 +- 3 files changed, 200 insertions(+), 142 deletions(-) diff --git a/Content.Server/Light/Components/LightReplacerComponent.cs b/Content.Server/Light/Components/LightReplacerComponent.cs index 8873ecf490..79e57a95f1 100644 --- a/Content.Server/Light/Components/LightReplacerComponent.cs +++ b/Content.Server/Light/Components/LightReplacerComponent.cs @@ -1,16 +1,9 @@ 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; @@ -27,137 +20,27 @@ namespace Content.Server.Light.Components { public override string Name => "LightReplacer"; - [DataField("sound")] private SoundSpecifier _sound = new SoundPathSpecifier("/Audio/Weapons/click.ogg"); + [DataField("sound")] + public 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!; + /// + /// Bulbs that were inside light replacer when it spawned + /// + [DataField("contents")] + public List Contents = new(); - 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; - } + /// + /// Bulbs that were inserted inside light replacer + /// + [ViewVariables] + public IContainer InsertedBulbs = default!; [Serializable] [DataDefinition] public class LightReplacerEntity { [DataField("name", customTypeSerializer: typeof(PrototypeIdSerializer))] - public string? PrototypeName; + public string PrototypeName = default!; [DataField("amount")] public int Amount; diff --git a/Content.Server/Light/EntitySystems/LightReplacerSystem.cs b/Content.Server/Light/EntitySystems/LightReplacerSystem.cs index fba3c80ce0..669801d4bf 100644 --- a/Content.Server/Light/EntitySystems/LightReplacerSystem.cs +++ b/Content.Server/Light/EntitySystems/LightReplacerSystem.cs @@ -3,54 +3,229 @@ using Content.Server.Storage.Components; using Content.Shared.ActionBlocker; using Content.Shared.Interaction; using Content.Shared.Interaction.Events; +using Content.Shared.Light; +using Content.Shared.Popups; using JetBrains.Annotations; +using Robust.Shared.Audio; +using Robust.Shared.Containers; using Robust.Shared.GameObjects; +using Robust.Shared.IoC; +using Robust.Shared.Localization; +using Robust.Shared.Player; +using System; +using System.Linq; namespace Content.Server.Light.EntitySystems { [UsedImplicitly] public class LightReplacerSystem : EntitySystem { + [Dependency] private readonly ActionBlockerSystem _blocker = default!; + [Dependency] private readonly PoweredLightSystem _poweredLight = default!; + [Dependency] private readonly SharedPopupSystem _popupSystem = default!; + public override void Initialize() { base.Initialize(); + SubscribeLocalEvent(OnInit); SubscribeLocalEvent(HandleInteract); SubscribeLocalEvent(HandleAfterInteract); } + private void OnInit(EntityUid uid, LightReplacerComponent replacer, ComponentInit args) + { + replacer.InsertedBulbs = ContainerHelpers.EnsureContainer(replacer.Owner, "light_replacer_storage"); + } + private void HandleAfterInteract(EntityUid uid, LightReplacerComponent component, AfterInteractEvent eventArgs) { + if (eventArgs.Handled) + return; + // standard interaction checks - if (!EntitySystem.Get().CanUse(eventArgs.User)) return; + if (!_blocker.CanUse(eventArgs.User)) return; if (!eventArgs.CanReach) return; // behaviour will depends on target type if (eventArgs.Target != null) { + var targetUid = eventArgs.Target.Uid; + // replace broken light in fixture? - if (eventArgs.Target.TryGetComponent(out PoweredLightComponent? fixture)) - component.TryReplaceBulb(fixture, eventArgs.User); + if (EntityManager.TryGetComponent(targetUid, out PoweredLightComponent? fixture)) + eventArgs.Handled = TryReplaceBulb(uid, targetUid, eventArgs.User.Uid, component, fixture); // add new bulb to light replacer container? - else if (eventArgs.Target.TryGetComponent(out LightBulbComponent? bulb)) - component.TryInsertBulb(bulb, eventArgs.User, true); + else if (EntityManager.TryGetComponent(targetUid, out LightBulbComponent? bulb)) + eventArgs.Handled = TryInsertBulb(uid, targetUid, eventArgs.User.Uid, true, component, bulb); } } private void HandleInteract(EntityUid uid, LightReplacerComponent component, InteractUsingEvent eventArgs) { + if (eventArgs.Handled) + return; + // standard interaction checks - if (!Get().CanInteract(eventArgs.User)) return; + if (!_blocker.CanInteract(eventArgs.User)) return; if (eventArgs.Used != null) { + var usedUid = eventArgs.Used.Uid; + // want to insert a new light bulb? - if (eventArgs.Used.TryGetComponent(out LightBulbComponent? bulb)) - component.TryInsertBulb(bulb, eventArgs.User, true); + if (EntityManager.TryGetComponent(usedUid, out LightBulbComponent ? bulb)) + eventArgs.Handled = TryInsertBulb(uid, usedUid, eventArgs.User.Uid, true, component, bulb); // add bulbs from storage? - else if (eventArgs.Used.TryGetComponent(out ServerStorageComponent? storage)) - component.TryInsertBulb(storage, eventArgs.User); + else if (EntityManager.TryGetComponent(usedUid, out ServerStorageComponent? storage)) + eventArgs.Handled = TryInsertBulbsFromStorage(uid, usedUid, eventArgs.User.Uid, component, storage); } } + + /// + /// Try to replace a light bulb in + /// using light replacer. Light fixture should have . + /// + /// True if successfully replaced light, false otherwise + public bool TryReplaceBulb(EntityUid replacerUid, EntityUid fixtureUid, EntityUid? userUid = null, + LightReplacerComponent? replacer = null, PoweredLightComponent? fixture = null) + { + if (!Resolve(replacerUid, ref replacer)) + return false; + if (!Resolve(fixtureUid, ref fixture)) + return false; + + // check if light bulb is broken or missing + var fixtureBulbUid = _poweredLight.GetBulb(fixture.Owner.Uid, fixture); + if (fixtureBulbUid != null) + { + if (!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 = replacer.InsertedBulbs.ContainedEntities.FirstOrDefault( + (e) => e.GetComponentOrNull()?.Type == fixture.BulbType); + + // found bulb in inserted storage + if (bulb != null) + { + // try to remove it + var hasRemoved = replacer.InsertedBulbs.Remove(bulb); + if (!hasRemoved) + return false; + } + // try to create new instance of bulb from LightReplacerEntity + else + { + var bulbEnt = replacer.Contents.FirstOrDefault((e) => e.Type == fixture.BulbType && e.Amount > 0); + + // found right bulb, let's spawn it + if (bulbEnt != null) + { + bulb = EntityManager.SpawnEntity(bulbEnt.PrototypeName, replacer.Owner.Transform.Coordinates); + bulbEnt.Amount--; + } + // not found any light bulbs + else + { + if (userUid != null) + { + var msg = Loc.GetString("comp-light-replacer-missing-light", + ("light-replacer", replacer.Owner)); + _popupSystem.PopupEntity(msg, replacerUid, Filter.Entities(userUid.Value)); + } + return false; + } + } + + // insert it into fixture + var wasReplaced = _poweredLight.ReplaceBulb(fixtureUid, bulb.Uid, fixture); + if (wasReplaced) + { + SoundSystem.Play(Filter.Pvs(replacerUid), replacer.Sound.GetSound(), + replacerUid, AudioParams.Default.WithVolume(-4f)); + } + + + return wasReplaced; + } + + /// + /// Try to insert a new bulb inside light replacer + /// + /// True if successfully inserted light, false otherwise + public bool TryInsertBulb(EntityUid replacerUid, EntityUid bulbUid, EntityUid? userUid = null, bool showTooltip = false, + LightReplacerComponent? replacer = null, LightBulbComponent? bulb = null) + { + if (!Resolve(replacerUid, ref replacer)) + return false; + if (!Resolve(bulbUid, ref bulb)) + return false; + + // only normal (non-broken) bulbs can be inserted inside light replacer + if (bulb.State != LightBulbState.Normal) + { + if (showTooltip && userUid != null) + { + var msg = Loc.GetString("comp-light-replacer-insert-broken-light"); + _popupSystem.PopupEntity(msg, replacerUid, Filter.Entities(userUid.Value)); + } + + return false; + } + + // try insert light and show message + var hasInsert = replacer.InsertedBulbs.Insert(bulb.Owner); + if (hasInsert && showTooltip && userUid != null) + { + var msg = Loc.GetString("comp-light-replacer-insert-light", + ("light-replacer", replacer.Owner), ("bulb", bulb.Owner)); + _popupSystem.PopupEntity(msg, replacerUid, Filter.Entities(userUid.Value)); + } + + return hasInsert; + } + + /// + /// Try to insert all light bulbs from storage (for example light tubes box) + /// + /// + /// Returns true if storage contained at least one light bulb + /// which was successfully inserted inside light replacer + /// + public bool TryInsertBulbsFromStorage(EntityUid replacerUid, EntityUid storageUid, EntityUid? userUid = null, + LightReplacerComponent? replacer = null, ServerStorageComponent? storage = null) + { + if (!Resolve(replacerUid, ref replacer)) + return false; + if (!Resolve(storageUid, ref storage)) + return false; + + if (storage.StoredEntities == null) + return false; + + var insertedBulbs = 0; + var storagedEnts = storage.StoredEntities.ToArray(); + foreach (var ent in storagedEnts) + { + if (EntityManager.TryGetComponent(ent.Uid, out LightBulbComponent? bulb)) + { + if (TryInsertBulb(replacerUid, ent.Uid, userUid, false, replacer, bulb)) + insertedBulbs++; + } + } + + // show some message if success + if (insertedBulbs > 0 && userUid != null) + { + var msg = Loc.GetString("comp-light-replacer-refill-from-storage", ("light-replacer", storage.Owner)); + _popupSystem.PopupEntity(msg, replacerUid, Filter.Entities(userUid.Value)); + } + + return insertedBulbs > 0; + } } } diff --git a/Resources/Prototypes/Entities/Objects/Tools/light_replacer.yml b/Resources/Prototypes/Entities/Objects/Tools/light_replacer.yml index 9f80d80b81..4eb4e78b29 100644 --- a/Resources/Prototypes/Entities/Objects/Tools/light_replacer.yml +++ b/Resources/Prototypes/Entities/Objects/Tools/light_replacer.yml @@ -11,9 +11,9 @@ sprite: Objects/Specific/Janitorial/light_replacer.rsi - type: LightReplacer contents: - - id: LightTube + - name: LightTube amount: 8 type: Tube - - id: LightBulb + - name: LightBulb amount: 5 type: Bulb