Fix light replacer and move it to ECS (#5053)
* Fixed broken replacer prototype * Light replacer ECS
This commit is contained in:
@@ -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<LightReplacerEntity> _contents = new();
|
||||
// bulbs that were inserted inside light replacer
|
||||
[ViewVariables] private IContainer _insertedBulbs = default!;
|
||||
/// <summary>
|
||||
/// Bulbs that were inside light replacer when it spawned
|
||||
/// </summary>
|
||||
[DataField("contents")]
|
||||
public List<LightReplacerEntity> Contents = new();
|
||||
|
||||
protected override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
_insertedBulbs = ContainerHelpers.EnsureContainer<Container>(Owner, "light_replacer_storage");
|
||||
}
|
||||
|
||||
public bool TryReplaceBulb(PoweredLightComponent fixture, IEntity? user = null)
|
||||
{
|
||||
// check if light bulb is broken or missing
|
||||
var lightSystem = EntitySystem.Get<PoweredLightSystem>();
|
||||
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<LightBulbComponent>()?.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;
|
||||
}
|
||||
/// <summary>
|
||||
/// Bulbs that were inserted inside light replacer
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
public IContainer InsertedBulbs = default!;
|
||||
|
||||
[Serializable]
|
||||
[DataDefinition]
|
||||
public class LightReplacerEntity
|
||||
{
|
||||
[DataField("name", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string? PrototypeName;
|
||||
public string PrototypeName = default!;
|
||||
|
||||
[DataField("amount")]
|
||||
public int Amount;
|
||||
|
||||
@@ -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<LightReplacerComponent, ComponentInit>(OnInit);
|
||||
SubscribeLocalEvent<LightReplacerComponent, InteractUsingEvent>(HandleInteract);
|
||||
SubscribeLocalEvent<LightReplacerComponent, AfterInteractEvent>(HandleAfterInteract);
|
||||
}
|
||||
|
||||
private void OnInit(EntityUid uid, LightReplacerComponent replacer, ComponentInit args)
|
||||
{
|
||||
replacer.InsertedBulbs = ContainerHelpers.EnsureContainer<Container>(replacer.Owner, "light_replacer_storage");
|
||||
}
|
||||
|
||||
private void HandleAfterInteract(EntityUid uid, LightReplacerComponent component, AfterInteractEvent eventArgs)
|
||||
{
|
||||
if (eventArgs.Handled)
|
||||
return;
|
||||
|
||||
// standard interaction checks
|
||||
if (!EntitySystem.Get<ActionBlockerSystem>().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<ActionBlockerSystem>().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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try to replace a light bulb in <paramref name="fixtureUid"/>
|
||||
/// using light replacer. Light fixture should have <see cref="PoweredLightComponent"/>.
|
||||
/// </summary>
|
||||
/// <returns>True if successfully replaced light, false otherwise</returns>
|
||||
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<LightBulbComponent>()?.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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try to insert a new bulb inside light replacer
|
||||
/// </summary>
|
||||
/// <returns>True if successfully inserted light, false otherwise</returns>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try to insert all light bulbs from storage (for example light tubes box)
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// Returns true if storage contained at least one light bulb
|
||||
/// which was successfully inserted inside light replacer
|
||||
/// </returns>
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user