diff --git a/Content.Client/Lightning/ClientMatchstickSystem.cs b/Content.Client/Lightning/ClientMatchstickSystem.cs new file mode 100644 index 00000000000000..c05abb8ccc34bf --- /dev/null +++ b/Content.Client/Lightning/ClientMatchstickSystem.cs @@ -0,0 +1,7 @@ +using Content.Shared.Light.EntitySystems; + +namespace Content.Client.Light.EntitySystems; + +public sealed class MatchstickSystem : SharedMatchstickSystem +{ +} diff --git a/Content.Server/Light/Components/MatchboxComponent.cs b/Content.Server/Light/Components/MatchboxComponent.cs deleted file mode 100644 index 12cd4e38808169..00000000000000 --- a/Content.Server/Light/Components/MatchboxComponent.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Content.Server.Light.Components -{ - // TODO make changes in icons when different threshold reached - // e.g. different icons for 10% 50% 100% - [RegisterComponent] - public sealed partial class MatchboxComponent : Component - { - } -} diff --git a/Content.Server/Light/Components/MatchstickComponent.cs b/Content.Server/Light/Components/MatchstickComponent.cs deleted file mode 100644 index 3c47f4c18b3831..00000000000000 --- a/Content.Server/Light/Components/MatchstickComponent.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Content.Server.Light.EntitySystems; -using Content.Shared.Smoking; -using Robust.Shared.Audio; - -namespace Content.Server.Light.Components -{ - [RegisterComponent] - [Access(typeof(MatchstickSystem))] - public sealed partial class MatchstickComponent : Component - { - /// - /// Current state to matchstick. Can be Unlit, Lit or Burnt. - /// - [DataField("state")] - public SmokableState CurrentState = SmokableState.Unlit; - - /// - /// How long will matchstick last in seconds. - /// - [ViewVariables(VVAccess.ReadOnly)] - [DataField("duration")] - public int Duration = 10; - - /// - /// Sound played when you ignite the matchstick. - /// - [DataField("igniteSound", required: true)] public SoundSpecifier IgniteSound = default!; - } -} diff --git a/Content.Server/Light/EntitySystems/MatchboxSystem.cs b/Content.Server/Light/EntitySystems/MatchboxSystem.cs deleted file mode 100644 index 9a73e44f8783af..00000000000000 --- a/Content.Server/Light/EntitySystems/MatchboxSystem.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Content.Server.Light.Components; -using Content.Server.Storage.EntitySystems; -using Content.Shared.Interaction; -using Content.Shared.Smoking; - -namespace Content.Server.Light.EntitySystems -{ - public sealed class MatchboxSystem : EntitySystem - { - [Dependency] private readonly MatchstickSystem _stickSystem = default!; - - public override void Initialize() - { - base.Initialize(); - SubscribeLocalEvent(OnInteractUsing, before: new[] { typeof(StorageSystem) }); - } - - private void OnInteractUsing(EntityUid uid, MatchboxComponent component, InteractUsingEvent args) - { - if (!args.Handled - && EntityManager.TryGetComponent(args.Used, out MatchstickComponent? matchstick) - && matchstick.CurrentState == SmokableState.Unlit) - { - _stickSystem.Ignite((args.Used, matchstick), args.User); - args.Handled = true; - } - } - } -} diff --git a/Content.Server/Light/EntitySystems/MatchstickSystem.cs b/Content.Server/Light/EntitySystems/MatchstickSystem.cs index 96e4695784dd4f..25f137611d5475 100644 --- a/Content.Server/Light/EntitySystems/MatchstickSystem.cs +++ b/Content.Server/Light/EntitySystems/MatchstickSystem.cs @@ -1,123 +1,47 @@ -using Content.Server.Atmos.EntitySystems; -using Content.Server.Light.Components; -using Content.Shared.Audio; -using Content.Shared.Interaction; -using Content.Shared.Item; using Content.Shared.Smoking; -using Content.Shared.Temperature; +using Content.Shared.Light.Components; +using Content.Server.Atmos.EntitySystems; using Robust.Server.GameObjects; -using Robust.Shared.Audio; -using Robust.Shared.Audio.Systems; -using Robust.Shared.Player; - -namespace Content.Server.Light.EntitySystems -{ - public sealed class MatchstickSystem : EntitySystem - { - [Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!; - [Dependency] private readonly SharedAppearanceSystem _appearance = default!; - [Dependency] private readonly SharedAudioSystem _audio = default!; - [Dependency] private readonly SharedItemSystem _item = default!; - [Dependency] private readonly SharedPointLightSystem _lights = default!; - [Dependency] private readonly TransformSystem _transformSystem = default!; - - private readonly HashSet> _litMatches = new(); - - public override void Initialize() - { - base.Initialize(); - SubscribeLocalEvent(OnInteractUsing); - SubscribeLocalEvent(OnIsHotEvent); - SubscribeLocalEvent(OnShutdown); - } - - private void OnShutdown(Entity ent, ref ComponentShutdown args) - { - _litMatches.Remove(ent); - } - - public override void Update(float frameTime) - { - base.Update(frameTime); - - foreach (var match in _litMatches) - { - if (match.Comp.CurrentState != SmokableState.Lit || Paused(match) || match.Comp.Deleted) - continue; - - var xform = Transform(match); - - if (xform.GridUid is not {} gridUid) - return; +using Robust.Shared.Timing; +using Content.Shared.Light.EntitySystems; - var position = _transformSystem.GetGridOrMapTilePosition(match, xform); +namespace Content.Server.Light.EntitySystems; - _atmosphereSystem.HotspotExpose(gridUid, position, 400, 50, match, true); - } - } - - private void OnInteractUsing(Entity ent, ref InteractUsingEvent args) - { - if (args.Handled || ent.Comp.CurrentState != SmokableState.Unlit) - return; - - var isHotEvent = new IsHotEvent(); - RaiseLocalEvent(args.Used, isHotEvent); - - if (!isHotEvent.IsHot) - return; +public sealed class MatchstickSystem : SharedMatchstickSystem +{ + [Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!; + [Dependency] private readonly TransformSystem _transformSystem = default!; + [Dependency] private readonly IGameTiming _timing = default!; - Ignite(ent, args.User); - args.Handled = true; - } + public override void Initialize() + { + base.Initialize(); + } - private void OnIsHotEvent(EntityUid uid, MatchstickComponent component, IsHotEvent args) - { - args.IsHot = component.CurrentState == SmokableState.Lit; - } + public override void Update(float frameTime) + { + var query = EntityQueryEnumerator(); - public void Ignite(Entity matchstick, EntityUid user) + while (query.MoveNext(out var uid, out var match)) { - var component = matchstick.Comp; + if (match.CurrentState != SmokableState.Lit) + continue; - // Play Sound - _audio.PlayPvs(component.IgniteSound, matchstick, AudioParams.Default.WithVariation(0.125f).WithVolume(-0.125f)); + var xform = Transform(uid); - // Change state - SetState(matchstick, component, SmokableState.Lit); - _litMatches.Add(matchstick); - matchstick.Owner.SpawnTimer(component.Duration * 1000, delegate - { - SetState(matchstick, component, SmokableState.Burnt); - _litMatches.Remove(matchstick); - }); - } + if (xform.GridUid is not { } gridUid) + continue; - private void SetState(EntityUid uid, MatchstickComponent component, SmokableState value) - { - component.CurrentState = value; + var position = _transformSystem.GetGridOrMapTilePosition(uid, xform); - if (_lights.TryGetLight(uid, out var pointLightComponent)) - { - _lights.SetEnabled(uid, component.CurrentState == SmokableState.Lit, pointLightComponent); - } - - if (EntityManager.TryGetComponent(uid, out ItemComponent? item)) - { - switch (component.CurrentState) - { - case SmokableState.Lit: - _item.SetHeldPrefix(uid, "lit", component: item); - break; - default: - _item.SetHeldPrefix(uid, "unlit", component: item); - break; - } - } + _atmosphereSystem.HotspotExpose(gridUid, position, 400, 50, uid, true); - if (EntityManager.TryGetComponent(uid, out AppearanceComponent? appearance)) + // Check if the match has expired. + var burnoutTime = match.TimeMatchWillBurnOut; + if (burnoutTime != null && _timing.CurTime > burnoutTime) { - _appearance.SetData(uid, SmokingVisuals.Smoking, component.CurrentState, appearance); + SetState(uid, match, SmokableState.Burnt); + match.TimeMatchWillBurnOut = null; } } } diff --git a/Content.Shared/Lightning/Components/MatchboxComponent.cs b/Content.Shared/Lightning/Components/MatchboxComponent.cs new file mode 100644 index 00000000000000..8747c231c0babb --- /dev/null +++ b/Content.Shared/Lightning/Components/MatchboxComponent.cs @@ -0,0 +1,11 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared.Light.Components; + +// TODO make changes in icons when different threshold reached +// e.g. different icons for 10% 50% 100% +[RegisterComponent, NetworkedComponent] +public sealed partial class MatchboxComponent : Component +{ +} + diff --git a/Content.Shared/Lightning/Components/MatchstickComponent.cs b/Content.Shared/Lightning/Components/MatchstickComponent.cs new file mode 100644 index 00000000000000..e741b5d9aa4c01 --- /dev/null +++ b/Content.Shared/Lightning/Components/MatchstickComponent.cs @@ -0,0 +1,35 @@ +using Content.Shared.Smoking; +using Robust.Shared.Audio; +using Robust.Shared.Serialization; +using Robust.Shared.GameStates; + +namespace Content.Shared.Light.Components; + +[NetworkedComponent, RegisterComponent] +[AutoGenerateComponentState, AutoGenerateComponentPause] +public sealed partial class MatchstickComponent : Component +{ + /// + /// Current state to matchstick. Can be Unlit, Lit or Burnt. + /// + [DataField("state")] + [AutoNetworkedField] + public SmokableState CurrentState = SmokableState.Unlit; + + /// + /// How long will matchstick last in seconds. + /// + [DataField("duration")] + public int Duration = 10; + + /// + /// The time that the match will burn out. If null, that means the match is unlit. + /// + [AutoNetworkedField, AutoPausedField] + public TimeSpan? TimeMatchWillBurnOut = null; + + /// + /// Sound played when you ignite the matchstick. + /// + [DataField("igniteSound", required: true)] public SoundSpecifier IgniteSound = default!; +} diff --git a/Content.Shared/Lightning/EntitySystems/MatchboxSystem.cs b/Content.Shared/Lightning/EntitySystems/MatchboxSystem.cs new file mode 100644 index 00000000000000..7bcbc654206df2 --- /dev/null +++ b/Content.Shared/Lightning/EntitySystems/MatchboxSystem.cs @@ -0,0 +1,28 @@ +using Content.Shared.Light.Components; +using Content.Shared.Storage.EntitySystems; +using Content.Shared.Interaction; +using Content.Shared.Smoking; + +namespace Content.Shared.Light.EntitySystems; + +public sealed class SharedMatchboxSystem : EntitySystem +{ + [Dependency] private readonly SharedMatchstickSystem _stickSystem = default!; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnInteractUsing, before: new[] { typeof(SharedStorageSystem) }); + } + + private void OnInteractUsing(EntityUid uid, MatchboxComponent component, InteractUsingEvent args) + { + if (args.Handled || !EntityManager.TryGetComponent(args.Used, out MatchstickComponent? matchstick)) + return; + + if (matchstick.CurrentState == SmokableState.Unlit) + _stickSystem.Ignite((args.Used, matchstick), args.User); + + args.Handled = true; + } +} diff --git a/Content.Shared/Lightning/EntitySystems/SharedMatchstickSystem.cs b/Content.Shared/Lightning/EntitySystems/SharedMatchstickSystem.cs new file mode 100644 index 00000000000000..d7f80a978790ce --- /dev/null +++ b/Content.Shared/Lightning/EntitySystems/SharedMatchstickSystem.cs @@ -0,0 +1,86 @@ +using Content.Shared.Interaction; +using Content.Shared.Item; +using Content.Shared.Smoking; +using Content.Shared.Temperature; +using Robust.Shared.Audio; +using Robust.Shared.Audio.Systems; +using Robust.Shared.Player; +using Content.Shared.Light.Components; +using Robust.Shared.Timing; + +namespace Content.Shared.Light.EntitySystems; + +public abstract class SharedMatchstickSystem : EntitySystem +{ + [Dependency] private readonly SharedAppearanceSystem _appearance = default!; + [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] private readonly SharedItemSystem _item = default!; + [Dependency] private readonly SharedPointLightSystem _lights = default!; + [Dependency] private readonly IGameTiming _timing = default!; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnInteractUsing); + SubscribeLocalEvent(OnIsHotEvent); + } + + private void OnInteractUsing(Entity ent, ref InteractUsingEvent args) + { + if (args.Handled || ent.Comp.CurrentState != SmokableState.Unlit) + return; + + var isHotEvent = new IsHotEvent(); + RaiseLocalEvent(args.Used, isHotEvent); + + if (!isHotEvent.IsHot) + return; + + Ignite(ent, args.User); + args.Handled = true; + } + + private void OnIsHotEvent(EntityUid uid, MatchstickComponent component, IsHotEvent args) + { + args.IsHot = component.CurrentState == SmokableState.Lit; + } + + public void Ignite(Entity matchstick, EntityUid user) + { + // Play Sound + _audio.PlayPredicted(matchstick.Comp.IgniteSound, matchstick, user, AudioParams.Default.WithVariation(0.125f).WithVolume(-0.125f)); + + // Change state + SetState(matchstick, matchstick.Comp, SmokableState.Lit); + matchstick.Comp.TimeMatchWillBurnOut = _timing.CurTime + TimeSpan.FromSeconds(matchstick.Comp.Duration); + + } + + protected void SetState(EntityUid uid, MatchstickComponent component, SmokableState value) + { + component.CurrentState = value; + + if (_lights.TryGetLight(uid, out var pointLightComponent)) + { + _lights.SetEnabled(uid, component.CurrentState == SmokableState.Lit, pointLightComponent); + } + + if (EntityManager.TryGetComponent(uid, out ItemComponent? item)) + { + switch (component.CurrentState) + { + case SmokableState.Lit: + _item.SetHeldPrefix(uid, "lit", component: item); + break; + default: + _item.SetHeldPrefix(uid, "unlit", component: item); + break; + } + } + + if (EntityManager.TryGetComponent(uid, out AppearanceComponent? appearance)) + { + _appearance.SetData(uid, SmokingVisuals.Smoking, component.CurrentState, appearance); + } + } +}