diff --git a/Content.Client/Lathe/LatheSystem.cs b/Content.Client/Lathe/LatheSystem.cs index f63e075927..24585f312f 100644 --- a/Content.Client/Lathe/LatheSystem.cs +++ b/Content.Client/Lathe/LatheSystem.cs @@ -8,6 +8,8 @@ namespace Content.Client.Lathe; public sealed class LatheSystem : SharedLatheSystem { + [Dependency] private readonly AppearanceSystem _appearance = default!; + public override void Initialize() { base.Initialize(); @@ -20,32 +22,19 @@ public sealed class LatheSystem : SharedLatheSystem if (args.Sprite == null) return; - if (args.Component.TryGetData(PowerDeviceVisuals.Powered, out bool powered) && + if (_appearance.TryGetData(uid, PowerDeviceVisuals.Powered, out bool powered, args.Component) && args.Sprite.LayerMapTryGet(PowerDeviceVisualLayers.Powered, out _)) { args.Sprite.LayerSetVisible(PowerDeviceVisualLayers.Powered, powered); } // Lathe specific stuff - if (args.Component.TryGetData(LatheVisuals.IsRunning, out bool isRunning)) + if (_appearance.TryGetData(uid, LatheVisuals.IsRunning, out bool isRunning, args.Component)) { var state = isRunning ? component.RunningState : component.IdleState; args.Sprite.LayerSetAnimationTime(LatheVisualLayers.IsRunning, 0f); args.Sprite.LayerSetState(LatheVisualLayers.IsRunning, state); } - - if (args.Component.TryGetData(LatheVisuals.IsInserting, out bool isInserting) - && args.Sprite.LayerMapTryGet(LatheVisualLayers.IsInserting, out var isInsertingLayer)) - { - if (args.Component.TryGetData(LatheVisuals.InsertingColor, out Color color) - && !component.IgnoreColor) - { - args.Sprite.LayerSetColor(isInsertingLayer, color); - } - - args.Sprite.LayerSetAnimationTime(isInsertingLayer, 0f); - args.Sprite.LayerSetVisible(isInsertingLayer, isInserting); - } } /// @@ -60,6 +49,5 @@ public sealed class LatheSystem : SharedLatheSystem public enum LatheVisualLayers : byte { - IsRunning, - IsInserting + IsRunning } diff --git a/Content.Client/Materials/MaterialStorageSystem.cs b/Content.Client/Materials/MaterialStorageSystem.cs index 27568f4c14..faad21fcf4 100644 --- a/Content.Client/Materials/MaterialStorageSystem.cs +++ b/Content.Client/Materials/MaterialStorageSystem.cs @@ -3,13 +3,43 @@ using Robust.Client.GameObjects; namespace Content.Client.Materials; -/// -/// This handles... -/// public sealed class MaterialStorageSystem : SharedMaterialStorageSystem { + [Dependency] private readonly AppearanceSystem _appearance = default!; [Dependency] private readonly TransformSystem _transform = default!; + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnAppearanceChange); + } + + private void OnAppearanceChange(EntityUid uid, MaterialStorageComponent component, ref AppearanceChangeEvent args) + { + if (args.Sprite == null) + return; + + if (!args.Sprite.LayerMapTryGet(MaterialStorageVisualLayers.Inserting, out var layer)) + return; + + if (!_appearance.TryGetData(uid, MaterialStorageVisuals.Inserting, out bool inserting, args.Component)) + return; + + if (inserting && TryComp(uid, out var insertingComp)) + { + args.Sprite.LayerSetAnimationTime(layer, 0f); + + args.Sprite.LayerSetVisible(layer, true); + if (insertingComp.MaterialColor != null) + args.Sprite.LayerSetColor(layer, insertingComp.MaterialColor.Value); + } + else + { + args.Sprite.LayerSetVisible(layer, false); + } + } + public override bool TryInsertMaterialEntity(EntityUid user, EntityUid toInsert, EntityUid receiver, MaterialStorageComponent? component = null) { if (!base.TryInsertMaterialEntity(user, toInsert, receiver, component)) @@ -18,3 +48,8 @@ public sealed class MaterialStorageSystem : SharedMaterialStorageSystem return true; } } + +public enum MaterialStorageVisualLayers : byte +{ + Inserting +} diff --git a/Content.Server/Lathe/Components/LatheInsertingComponent.cs b/Content.Server/Lathe/Components/LatheInsertingComponent.cs deleted file mode 100644 index ef464ca853..0000000000 --- a/Content.Server/Lathe/Components/LatheInsertingComponent.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace Content.Server.Lathe.Components -{ - /// - /// For EntityQuery to keep track of which lathes are inserting - /// - [RegisterComponent] - public sealed class LatheInsertingComponent : Component - { - /// - /// Remaining insertion time, in seconds. - /// - [DataField("timeRemaining", required: true)] - public float TimeRemaining; - } -} diff --git a/Content.Server/Lathe/LatheSystem.cs b/Content.Server/Lathe/LatheSystem.cs index 6332e302ca..3892204b41 100644 --- a/Content.Server/Lathe/LatheSystem.cs +++ b/Content.Server/Lathe/LatheSystem.cs @@ -33,7 +33,6 @@ namespace Content.Server.Lathe public override void Initialize() { base.Initialize(); - SubscribeLocalEvent(OnMaterialEntityInserted); SubscribeLocalEvent(OnGetWhitelist); SubscribeLocalEvent(OnMapInit); SubscribeLocalEvent(OnPowerChanged); @@ -45,24 +44,13 @@ namespace Content.Server.Lathe SubscribeLocalEvent(OnLatheSyncRequestMessage); SubscribeLocalEvent((u,c,_) => UpdateUserInterfaceState(u,c)); - SubscribeLocalEvent((u,c,_) => UpdateUserInterfaceState(u,c)); + SubscribeLocalEvent(OnMaterialAmountChanged); SubscribeLocalEvent(OnGetRecipes); } public override void Update(float frameTime) { - foreach (var comp in EntityQuery()) - { - comp.TimeRemaining -= frameTime; - - if (comp.TimeRemaining > 0) - continue; - - UpdateInsertingAppearance(comp.Owner, false); - RemCompDeferred(comp.Owner, comp); - } - foreach (var (comp, lathe) in EntityQuery()) { if (lathe.CurrentRecipe == null) @@ -73,7 +61,7 @@ namespace Content.Server.Lathe } } - private void OnGetWhitelist(EntityUid uid, LatheComponent component, GetMaterialWhitelistEvent args) + private void OnGetWhitelist(EntityUid uid, LatheComponent component, ref GetMaterialWhitelistEvent args) { if (args.Storage != uid) return; @@ -203,6 +191,11 @@ namespace Content.Server.Lathe args.Recipes = args.Recipes.Union(component.RecipeIds.Where(r => latheComponent.DynamicRecipes.Contains(r))).ToList(); } + private void OnMaterialAmountChanged(EntityUid uid, LatheComponent component, ref MaterialAmountChangedEvent args) + { + UpdateUserInterfaceState(uid, component); + } + /// /// Initialize the UI and appearance. /// Appearance requires initialization or the layers break @@ -215,15 +208,6 @@ namespace Content.Server.Lathe _materialStorage.UpdateMaterialWhitelist(uid); } - private void OnMaterialEntityInserted(EntityUid uid, LatheComponent component, MaterialEntityInsertedEvent args) - { - var lastMat = args.MaterialComp.Materials.Keys.Last(); - // We need the prototype to get the color - _proto.TryIndex(lastMat, out MaterialPrototype? matProto); - EnsureComp(uid).TimeRemaining = component.InsertionTime; - UpdateInsertingAppearance(uid, true, matProto?.Color); - } - /// /// Sets the machine sprite to either play the running animation /// or stop. @@ -233,17 +217,6 @@ namespace Content.Server.Lathe _appearance.SetData(uid, LatheVisuals.IsRunning, isRunning); } - /// - /// Sets the machine sprite to play the inserting animation - /// and sets the color of the inserted mat if applicable - /// - private void UpdateInsertingAppearance(EntityUid uid, bool isInserting, Color? color = null) - { - _appearance.SetData(uid, LatheVisuals.IsInserting, isInserting); - if (color != null) - _appearance.SetData(uid, LatheVisuals.InsertingColor, color); - } - private void OnPowerChanged(EntityUid uid, LatheComponent component, ref PowerChangedEvent args) { if (!args.Powered) @@ -297,8 +270,10 @@ namespace Content.Server.Lathe count++; } if (count > 0 && args.Session.AttachedEntity != null) + { _adminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(args.Session.AttachedEntity.Value):player} queued {count} {recipe.Name} at {ToPrettyString(uid):lathe}"); + } } TryStartProducing(uid, component); UpdateUserInterfaceState(uid, component); diff --git a/Content.Server/Materials/MaterialStorageSystem.cs b/Content.Server/Materials/MaterialStorageSystem.cs index 29e803b745..8dbdfaf97c 100644 --- a/Content.Server/Materials/MaterialStorageSystem.cs +++ b/Content.Server/Materials/MaterialStorageSystem.cs @@ -54,7 +54,6 @@ public sealed class MaterialStorageSystem : SharedMaterialStorageSystem var count = stack?.Count ?? 1; _adminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(user):player} inserted {count} {ToPrettyString(toInsert):inserted} into {ToPrettyString(receiver):receiver}"); - return true; } } diff --git a/Content.Shared/Lathe/LatheComponent.cs b/Content.Shared/Lathe/LatheComponent.cs index abf462e936..beb840e5b4 100644 --- a/Content.Shared/Lathe/LatheComponent.cs +++ b/Content.Shared/Lathe/LatheComponent.cs @@ -28,12 +28,6 @@ namespace Content.Shared.Lathe [DataField("queue")] public List Queue = new(); - /// - /// How long the inserting animation will play - /// - [DataField("insertionTime")] - public float InsertionTime = 0.79f; // 0.01 off for animation timing - /// /// The sound that plays when the lathe is producing an item, if any /// @@ -46,9 +40,6 @@ namespace Content.Shared.Lathe [DataField("runningState", required: true)] public string RunningState = default!; - - [DataField("ignoreColor")] - public bool IgnoreColor; #endregion /// diff --git a/Content.Shared/Materials/InsertingMaterialStorageComponent.cs b/Content.Shared/Materials/InsertingMaterialStorageComponent.cs new file mode 100644 index 0000000000..6c0ed0f969 --- /dev/null +++ b/Content.Shared/Materials/InsertingMaterialStorageComponent.cs @@ -0,0 +1,31 @@ +using Robust.Shared.GameStates; +using Robust.Shared.Serialization; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; + +namespace Content.Shared.Materials; + +[RegisterComponent, NetworkedComponent] +public sealed class InsertingMaterialStorageComponent : Component +{ + /// + /// The time when insertion ends. + /// + [DataField("endTime", customTypeSerializer: typeof(TimeOffsetSerializer)), ViewVariables(VVAccess.ReadWrite)] + public TimeSpan EndTime; + + [ViewVariables] + public Color? MaterialColor; +} + +[Serializable, NetSerializable] +public sealed class InsertingMaterialStorageComponentState : ComponentState +{ + public TimeSpan EndTime; + public Color? MaterialColor; + + public InsertingMaterialStorageComponentState(TimeSpan endTime, Color? materialColor) + { + EndTime = endTime; + MaterialColor = materialColor; + } +} diff --git a/Content.Shared/Materials/MaterialStorageComponent.cs b/Content.Shared/Materials/MaterialStorageComponent.cs index 5f0d5a360d..0bc0c280c2 100644 --- a/Content.Shared/Materials/MaterialStorageComponent.cs +++ b/Content.Shared/Materials/MaterialStorageComponent.cs @@ -2,6 +2,7 @@ using Content.Shared.Whitelist; using Robust.Shared.Audio; using Robust.Shared.GameStates; using Robust.Shared.Serialization; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; @@ -38,44 +39,56 @@ public sealed class MaterialStorageComponent : Component [DataField("materialWhiteList", customTypeSerializer: typeof(PrototypeIdListSerializer))] public List? MaterialWhiteList; + /// + /// Whether or not the visualization for the insertion animation + /// should ignore the color of the material being inserted. + /// + [DataField("ignoreColor")] + public bool IgnoreColor; + /// /// The sound that plays when inserting an item into the storage /// [DataField("insertingSound")] public SoundSpecifier? InsertingSound; + + /// + /// How long the inserting animation will play + /// + [DataField("insertionTime", customTypeSerializer: typeof(TimeOffsetSerializer))] + public TimeSpan InsertionTime = TimeSpan.FromSeconds(0.79f); // 0.01 off for animation timing +} + +[Serializable, NetSerializable] +public enum MaterialStorageVisuals : byte +{ + Inserting } /// /// event raised on the materialStorage when a material entity is inserted into it. /// -public readonly struct MaterialEntityInsertedEvent +[ByRefEvent] +public readonly record struct MaterialEntityInsertedEvent(MaterialComponent MaterialComp) { - public readonly MaterialComponent MaterialComp; - - public MaterialEntityInsertedEvent(MaterialComponent materials) - { - MaterialComp = materials; - } + public readonly MaterialComponent MaterialComp = MaterialComp; } /// /// Event raised when a material amount is changed /// -public readonly struct MaterialAmountChangedEvent -{ +[ByRefEvent] +public readonly record struct MaterialAmountChangedEvent; -} - -public sealed class GetMaterialWhitelistEvent : EntityEventArgs +/// +/// Event raised to get all the materials that the +/// +[ByRefEvent] +public record struct GetMaterialWhitelistEvent(EntityUid Storage) { - public readonly EntityUid Storage; + public readonly EntityUid Storage = Storage; public List Whitelist = new(); - - public GetMaterialWhitelistEvent(EntityUid storage) - { - Storage = storage; - } } [Serializable, NetSerializable] diff --git a/Content.Shared/Materials/SharedMaterialStorageSystem.cs b/Content.Shared/Materials/SharedMaterialStorageSystem.cs index b1bbc1e1a7..2ade6b5705 100644 --- a/Content.Shared/Materials/SharedMaterialStorageSystem.cs +++ b/Content.Shared/Materials/SharedMaterialStorageSystem.cs @@ -1,8 +1,10 @@ -using System.Linq; +using System.Linq; using Content.Shared.Interaction; using Content.Shared.Stacks; using JetBrains.Annotations; using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; +using Robust.Shared.Timing; namespace Content.Shared.Materials; @@ -12,14 +14,40 @@ namespace Content.Shared.Materials; /// public abstract class SharedMaterialStorageSystem : EntitySystem { + [Dependency] private readonly SharedAppearanceSystem _appearance = default!; + [Dependency] private readonly IGameTiming _timing = default!; + [Dependency] private readonly IPrototypeManager _prototype = default!; + /// public override void Initialize() { base.Initialize(); + SubscribeLocalEvent(OnMapInit); SubscribeLocalEvent(OnInteractUsing); SubscribeLocalEvent(OnGetState); SubscribeLocalEvent(OnHandleState); + SubscribeLocalEvent(OnGetInsertingState); + SubscribeLocalEvent(OnHandleInsertingState); + SubscribeLocalEvent(OnUnpaused); + } + + public override void Update(float frameTime) + { + base.Update(frameTime); + foreach (var inserting in EntityQuery()) + { + if (_timing.CurTime < inserting.EndTime) + continue; + + _appearance.SetData(inserting.Owner, MaterialStorageVisuals.Inserting, false); + RemComp(inserting.Owner, inserting); + } + } + + private void OnMapInit(EntityUid uid, MaterialStorageComponent component, MapInitEvent args) + { + _appearance.SetData(uid, MaterialStorageVisuals.Inserting, false); } private void OnGetState(EntityUid uid, MaterialStorageComponent component, ref ComponentGetState args) @@ -38,6 +66,25 @@ public abstract class SharedMaterialStorageSystem : EntitySystem component.MaterialWhiteList = new List(state.MaterialWhitelist); } + private void OnGetInsertingState(EntityUid uid, InsertingMaterialStorageComponent component, ref ComponentGetState args) + { + args.State = new InsertingMaterialStorageComponentState(component.EndTime, component.MaterialColor); + } + + private void OnHandleInsertingState(EntityUid uid, InsertingMaterialStorageComponent component, ref ComponentHandleState args) + { + if (args.Current is not InsertingMaterialStorageComponentState state) + return; + + component.EndTime = state.EndTime; + component.MaterialColor = state.MaterialColor; + } + + private void OnUnpaused(EntityUid uid, InsertingMaterialStorageComponent component, ref EntityUnpausedEvent args) + { + component.EndTime += args.PausedTime; + } + /// /// Gets the volume of a specified material contained in this storage. /// @@ -128,7 +175,8 @@ public abstract class SharedMaterialStorageSystem : EntitySystem component.Storage.Add(materialId, 0); component.Storage[materialId] += volume; - RaiseLocalEvent(uid, new MaterialAmountChangedEvent()); + var ev = new MaterialAmountChangedEvent(); + RaiseLocalEvent(uid, ref ev); Dirty(component); return true; } @@ -171,7 +219,18 @@ public abstract class SharedMaterialStorageSystem : EntitySystem TryChangeMaterialAmount(receiver, mat, vol * multiplier, component); } - RaiseLocalEvent(component.Owner, new MaterialEntityInsertedEvent(material)); + var insertingComp = EnsureComp(receiver); + insertingComp.EndTime = _timing.CurTime + component.InsertionTime; + if (!component.IgnoreColor) + { + _prototype.TryIndex(material.Materials.Keys.Last(), out var lastMat); + insertingComp.MaterialColor = lastMat?.Color; + } + _appearance.SetData(receiver, MaterialStorageVisuals.Inserting, true); + Dirty(insertingComp); + + var ev = new MaterialEntityInsertedEvent(material); + RaiseLocalEvent(component.Owner, ref ev); return true; } @@ -186,7 +245,7 @@ public abstract class SharedMaterialStorageSystem : EntitySystem if (!Resolve(uid, ref component, false)) return; var ev = new GetMaterialWhitelistEvent(uid); - RaiseLocalEvent(uid, ev); + RaiseLocalEvent(uid, ref ev); component.MaterialWhiteList = ev.Whitelist; Dirty(component); } diff --git a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml index 66ca596482..4755dbd9bc 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml @@ -15,7 +15,7 @@ shader: unshaded map: ["enum.PowerDeviceVisualLayers.Powered"] - state: inserting - map: ["enum.LatheVisualLayers.IsInserting"] + map: ["enum.MaterialStorageVisualLayers.Inserting"] - state: panel map: ["enum.WiresVisualLayers.MaintenancePanel"] - type: Appearance @@ -102,7 +102,7 @@ shader: unshaded map: ["enum.PowerDeviceVisualLayers.Powered"] - state: inserting - map: ["enum.LatheVisualLayers.IsInserting"] + map: ["enum.MaterialStorageVisualLayers.Inserting"] - state: panel map: ["enum.WiresVisualLayers.MaintenancePanel"] - type: Appearance @@ -335,7 +335,7 @@ - state: fab-idle map: ["enum.LatheVisualLayers.IsRunning"] - state: fab-load - map: ["enum.LatheVisualLayers.IsInserting"] + map: ["enum.MaterialStorageVisualLayers.Inserting"] - state: fab-o map: ["enum.WiresVisualLayers.MaintenancePanel"] - type: Machine @@ -376,7 +376,7 @@ shader: unshaded map: ["enum.PowerDeviceVisualLayers.Powered"] - state: inserting - map: ["enum.LatheVisualLayers.IsInserting"] + map: ["enum.MaterialStorageVisualLayers.Inserting"] - state: panel map: ["enum.WiresVisualLayers.MaintenancePanel"] - type: Machine @@ -432,7 +432,7 @@ shader: unshaded map: ["enum.PowerDeviceVisualLayers.Powered"] - state: inserting - map: ["enum.LatheVisualLayers.IsInserting"] + map: ["enum.MaterialStorageVisualLayers.Inserting"] - state: panel map: ["enum.WiresVisualLayers.MaintenancePanel"] - type: Lathe @@ -579,18 +579,18 @@ shader: unshaded map: ["enum.PowerDeviceVisualLayers.Powered"] - state: inserting - map: ["enum.LatheVisualLayers.IsInserting"] + map: ["enum.MaterialStorageVisualLayers.Inserting"] - state: panel map: ["enum.WiresVisualLayers.MaintenancePanel"] - type: Machine board: OreProcessorMachineCircuitboard - type: MaterialStorage dropOnDeconstruct: false #should drop ores instead of ingots/sheets + ignoreColor: true whitelist: tags: - Ore - type: Lathe - ignoreColor: true staticRecipes: - SheetSteel30 - SheetGlass30