From bbd648242040844917e3eb6d1bff4182ac93c4d2 Mon Sep 17 00:00:00 2001
From: Leon Friedrich <60421075+ElectroJr@users.noreply.github.com>
Date: Thu, 4 Aug 2022 12:38:56 +1200
Subject: [PATCH] Fix lathe unanchor interaction & general cleanup (#10156)
---
.../Lathe/Components/LatheComponent.cs | 17 +-
.../Components/LatheInsertingComponent.cs | 8 +-
.../Components/LatheProducingComponent.cs | 17 +-
Content.Server/Lathe/LatheSystem.cs | 252 ++++++++----------
Content.Shared/Lathe/LatheMessages.cs | 4 +-
5 files changed, 144 insertions(+), 154 deletions(-)
diff --git a/Content.Server/Lathe/Components/LatheComponent.cs b/Content.Server/Lathe/Components/LatheComponent.cs
index 5902c31d28..b3ac8d1f21 100644
--- a/Content.Server/Lathe/Components/LatheComponent.cs
+++ b/Content.Server/Lathe/Components/LatheComponent.cs
@@ -29,13 +29,10 @@ namespace Content.Server.Lathe.Components
///
/// The lathe's construction queue
///
- [ViewVariables]
- public Queue Queue { get; } = new();
- ///
- /// The recipe the lathe is currently producing
- ///
- [ViewVariables]
- public LatheRecipePrototype? ProducingRecipe;
+ [DataField("queue", customTypeSerializer: typeof(PrototypeIdListSerializer))]
+ public List Queue { get; } = new();
+ // TODO queue serializer.
+
///
/// How long the inserting animation will play
///
@@ -46,12 +43,6 @@ namespace Content.Server.Lathe.Components
///
[DataField("insertionAccumulator")]
public float InsertionAccumulator = 0f;
- ///
- /// Production accumulator for the production time.
- ///
- [ViewVariables]
- [DataField("producingAccumulator")]
- public float ProducingAccumulator = 0f;
///
/// The sound that plays when the lathe is producing an item, if any
diff --git a/Content.Server/Lathe/Components/LatheInsertingComponent.cs b/Content.Server/Lathe/Components/LatheInsertingComponent.cs
index e808c4d26d..f56ef45976 100644
--- a/Content.Server/Lathe/Components/LatheInsertingComponent.cs
+++ b/Content.Server/Lathe/Components/LatheInsertingComponent.cs
@@ -5,5 +5,11 @@ namespace Content.Server.Lathe.Components
///
[RegisterComponent]
public sealed class LatheInsertingComponent : Component
- {}
+ {
+ ///
+ /// Remaining insertion time, in seconds.
+ ///
+ [DataField("timeRemaining", required: true)]
+ public float TimeRemaining;
+ }
}
diff --git a/Content.Server/Lathe/Components/LatheProducingComponent.cs b/Content.Server/Lathe/Components/LatheProducingComponent.cs
index 55ff79d625..89a7c96e06 100644
--- a/Content.Server/Lathe/Components/LatheProducingComponent.cs
+++ b/Content.Server/Lathe/Components/LatheProducingComponent.cs
@@ -1,3 +1,6 @@
+using Content.Shared.Research.Prototypes;
+using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
+
namespace Content.Server.Lathe.Components
{
///
@@ -5,5 +8,17 @@ namespace Content.Server.Lathe.Components
///
[RegisterComponent]
public sealed class LatheProducingComponent : Component
- {}
+ {
+ ///
+ /// The recipe the lathe is currently producing
+ ///
+ [DataField("recipe", required:true, customTypeSerializer:typeof(PrototypeIdSerializer))]
+ public string? Recipe;
+
+ ///
+ /// Remaining production 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 9d16f9c6c9..6ca7b5855a 100644
--- a/Content.Server/Lathe/LatheSystem.cs
+++ b/Content.Server/Lathe/LatheSystem.cs
@@ -6,18 +6,16 @@ using Content.Server.Research.Components;
using Content.Shared.Interaction;
using Content.Server.Materials;
using Content.Server.Popups;
-using Content.Server.Power.Components;
using Content.Server.Power.EntitySystems;
using Content.Server.Research;
using Content.Server.Stack;
-using Content.Server.UserInterface;
using Content.Shared.Research.Components;
using Robust.Server.GameObjects;
using Robust.Shared.Prototypes;
using Robust.Shared.Player;
-using Robust.Shared.Audio;
using JetBrains.Annotations;
using System.Linq;
+using Robust.Server.Player;
namespace Content.Server.Lathe
{
@@ -26,59 +24,40 @@ namespace Content.Server.Lathe
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
-
+ [Dependency] private readonly SharedAudioSystem _audioSys = default!;
+ [Dependency] private readonly UserInterfaceSystem _uiSys = default!;
+ [Dependency] private readonly ResearchSystem _researchSys = default!;
+
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent(OnInteractUsing);
SubscribeLocalEvent(OnComponentInit);
+ SubscribeLocalEvent(OnLatheQueueRecipeMessage);
+ SubscribeLocalEvent(OnLatheSyncRequestMessage);
+ SubscribeLocalEvent(OnLatheServerSelectionMessage);
+ SubscribeLocalEvent(OnLatheServerSyncMessage);
}
- // These queues are to add/remove COMPONENTS to the lathes
- private Queue ProducingAddQueue = new();
- private Queue ProducingRemoveQueue = new();
- private Queue InsertingAddQueue = new();
- private Queue InsertingRemoveQueue = new();
-
public override void Update(float frameTime)
{
- foreach (var uid in ProducingAddQueue)
- EnsureComp(uid);
- ProducingAddQueue.Clear();
- foreach (var uid in ProducingRemoveQueue)
- RemComp(uid);
- ProducingRemoveQueue.Clear();
- foreach (var uid in InsertingAddQueue)
- EnsureComp(uid);
- InsertingAddQueue.Clear();
- foreach (var uid in InsertingRemoveQueue)
- RemComp(uid);
- InsertingRemoveQueue.Clear();
-
- foreach (var (insertingComp, lathe) in EntityQuery(false))
+ foreach (var comp in EntityQuery())
{
- if (lathe.InsertionAccumulator < lathe.InsertionTime)
- {
- lathe.InsertionAccumulator += frameTime;
+ comp.TimeRemaining -= frameTime;
+
+ if (comp.TimeRemaining > 0)
continue;
- }
- lathe.InsertionAccumulator = 0;
- UpdateInsertingAppearance(lathe.Owner, false);
- InsertingRemoveQueue.Enqueue(lathe.Owner);
+
+ UpdateInsertingAppearance(comp.Owner, false);
+ RemCompDeferred(comp.Owner, comp);
}
- foreach (var (producingComp, lathe) in EntityQuery(false))
+ foreach (var comp in EntityQuery())
{
- if (lathe.ProducingRecipe == null)
- continue;
- if (lathe.ProducingAccumulator < lathe.ProducingRecipe.CompleteTime.TotalSeconds)
- {
- lathe.ProducingAccumulator += frameTime;
- continue;
- }
- lathe.ProducingAccumulator = 0;
+ comp.TimeRemaining -= frameTime;
- FinishProducing(lathe.ProducingRecipe, lathe, true);
+ if (comp.TimeRemaining <= 0)
+ FinishProducing(comp.Owner, comp);
}
}
@@ -88,12 +67,6 @@ namespace Content.Server.Lathe
///
private void OnComponentInit(EntityUid uid, LatheComponent component, ComponentInit args)
{
- component.UserInterface = uid.GetUIOrNull(LatheUiKey.Key);
- if (component.UserInterface != null)
- {
- component.UserInterface.OnReceiveMessage += msg => UserInterfaceOnOnReceiveMessage(uid, component, msg);
- }
-
if (TryComp(uid, out var appearance))
{
appearance.SetData(LatheVisuals.IsInserting, false);
@@ -111,9 +84,13 @@ namespace Content.Server.Lathe
return;
foreach (var recipe in recipes)
+ {
foreach (var mat in recipe.RequiredMaterials)
+ {
if (!component.MaterialWhiteList.Contains(mat.Key))
component.MaterialWhiteList.Add(mat.Key);
+ }
+ }
}
///
@@ -124,13 +101,14 @@ namespace Content.Server.Lathe
{
if (args.Handled)
return;
- args.Handled = true;
if (!TryComp(uid, out var storage)
|| !TryComp(args.Used, out var material)
|| component.LatheWhitelist?.IsValid(args.Used) == false)
return;
+ args.Handled = true;
+
var matUsed = false;
foreach (var mat in material.Materials)
if (component.MaterialWhiteList.Contains(mat.ID))
@@ -160,6 +138,7 @@ namespace Content.Server.Lathe
// Check if it can take ALL of the material's volume.
if (storage.StorageLimit > 0 && !storage.CanTakeAmount(totalAmount))
return;
+
var lastMat = string.Empty;
foreach (var (mat, vol) in material._materials)
{
@@ -169,17 +148,18 @@ namespace Content.Server.Lathe
// Play a sound when inserting, if any
if (component.InsertingSound != null)
- {
- SoundSystem.Play(component.InsertingSound.GetSound(), Filter.Pvs(component.Owner, entityManager: EntityManager), component.Owner);
- }
+ _audioSys.PlayPvs(component.InsertingSound, uid);
// We need the prototype to get the color
_prototypeManager.TryIndex(lastMat, out MaterialPrototype? matProto);
EntityManager.QueueDeleteEntity(args.Used);
- InsertingAddQueue.Enqueue(uid);
+
+ EnsureComp(uid).TimeRemaining = component.InsertionTime;
+
_popupSystem.PopupEntity(Loc.GetString("machine-insert-item", ("machine", uid),
("item", args.Used)), uid, Filter.Entities(args.User));
+
if (matProto != null)
{
UpdateInsertingAppearance(uid, true, matProto.Color);
@@ -191,30 +171,34 @@ namespace Content.Server.Lathe
/// This handles the checks to start producing an item, and
/// starts up the sound and visuals
///
- private void Produce(LatheComponent component, LatheRecipePrototype recipe, bool SkipCheck = false)
+ private bool TryStartProducing(EntityUid uid, LatheProducingComponent? prodComp = null, LatheComponent? component = null)
{
- if (!component.CanProduce(recipe)
- || !TryComp(component.Owner, out MaterialStorageComponent? storage))
+ if (!Resolve(uid, ref component) || component.Queue.Count == 0)
+ return false;
+
+ if (!this.IsPowered(uid, EntityManager))
+ return false;
+
+ var recipeId = component.Queue[0];
+
+ if (!_prototypeManager.TryIndex(recipeId, out var recipe))
{
- FinishProducing(recipe, component, false);
- return;
+ // recipie does not exist. Remove and try produce the next item.
+ component.Queue.RemoveAt(0);
+ return TryStartProducing(uid, prodComp, component);
}
+
+ if (!component.CanProduce(recipe) || !TryComp(uid, out MaterialStorageComponent? storage))
+ return false;
- if (!SkipCheck && HasComp(component.Owner))
- {
- FinishProducing(recipe, component, false);
- return;
- }
+ prodComp ??= EnsureComp(uid);
- if (!this.IsPowered(component.Owner, EntityManager))
- {
- FinishProducing(recipe, component, false);
- return;
- }
+ if (prodComp.Recipe != null)
+ return false;
- component.UserInterface?.SendMessage(new LatheFullQueueMessage(GetIdQueue(component)));
-
- component.ProducingRecipe = recipe;
+ component.Queue.RemoveAt(0);
+ prodComp.Recipe = recipeId;
+ prodComp.TimeRemaining = (float)recipe.CompleteTime.TotalSeconds;
foreach (var (material, amount) in recipe.RequiredMaterials)
{
@@ -222,33 +206,42 @@ namespace Content.Server.Lathe
storage.RemoveMaterial(material, amount);
}
- component.UserInterface?.SendMessage(new LatheProducingRecipeMessage(recipe.ID));
+ // Again, this should really just be a bui state instead of two separate messages.
+ _uiSys.TrySendUiMessage(uid, LatheUiKey.Key, new LatheProducingRecipeMessage(recipe.ID));
+ _uiSys.TrySendUiMessage(uid, LatheUiKey.Key, new LatheFullQueueMessage(component.Queue));
+
if (component.ProducingSound != null)
- {
- SoundSystem.Play(component.ProducingSound.GetSound(), Filter.Pvs(component.Owner), component.Owner);
- }
- UpdateRunningAppearance(component.Owner, true);
- ProducingAddQueue.Enqueue(component.Owner);
+ _audioSys.PlayPvs(component.ProducingSound, component.Owner);
+
+ UpdateRunningAppearance(uid, true);
+ return true;
}
///
/// If we were able to produce the recipe,
/// spawn it and cleanup. If we weren't, just do cleanup.
///
- private void FinishProducing(LatheRecipePrototype recipe, LatheComponent component, bool productionSucceeded = true)
+ private void FinishProducing(EntityUid uid, LatheProducingComponent prodComp)
{
- component.ProducingRecipe = null;
- if (productionSucceeded)
- EntityManager.SpawnEntity(recipe.Result, Comp(component.Owner).Coordinates);
- component.UserInterface?.SendMessage(new LatheStoppedProducingRecipeMessage());
- // Continue to next in queue if there are items left
- if (component.Queue.Count > 0)
+ if (prodComp.Recipe == null || !_prototypeManager.TryIndex(prodComp.Recipe, out var recipe))
{
- Produce(component, component.Queue.Dequeue(), true);
+ RemCompDeferred(prodComp.Owner, prodComp);
+ UpdateRunningAppearance(uid, false);
return;
}
- ProducingRemoveQueue.Enqueue(component.Owner);
- UpdateRunningAppearance(component.Owner, false);
+
+ Spawn(recipe.Result, Transform(uid).Coordinates);
+ prodComp.Recipe = null;
+
+ // TODO this should probably just be a BUI state, not a special message.
+ _uiSys.TrySendUiMessage(uid, LatheUiKey.Key, new LatheStoppedProducingRecipeMessage());
+
+ // Continue to next in queue if there are items left
+ if (TryStartProducing(uid, prodComp))
+ return;
+
+ RemComp(prodComp.Owner, prodComp);
+ UpdateRunningAppearance(uid, false);
}
///
@@ -277,64 +270,49 @@ namespace Content.Server.Lathe
appearance.SetData(LatheVisuals.InsertingColor, color);
}
- ///
- /// Handles all the button presses in the lathe UI
- ///
- private void UserInterfaceOnOnReceiveMessage(EntityUid uid, LatheComponent component, ServerBoundUserInterfaceMessage message)
+ #region UI Messages
+
+ private void OnLatheQueueRecipeMessage(EntityUid uid, LatheComponent component, LatheQueueRecipeMessage args)
{
- if (!this.IsPowered(uid, EntityManager))
- return;
-
- switch (message.Message)
+ if (_prototypeManager.TryIndex(args.ID, out LatheRecipePrototype? recipe))
{
- case LatheQueueRecipeMessage msg:
- _prototypeManager.TryIndex(msg.ID, out LatheRecipePrototype? recipe);
- if (recipe != null!)
- for (var i = 0; i < msg.Quantity; i++)
- {
- component.Queue.Enqueue(recipe);
- component.UserInterface?.SendMessage(new LatheFullQueueMessage(GetIdQueue(component)));
- }
- if (!HasComp(component.Owner) && component.Queue.Count > 0)
- Produce(component, component.Queue.Dequeue());
+ for (var i = 0; i < args.Quantity; i++)
+ {
+ component.Queue.Add(recipe.ID);
+ }
- break;
- case LatheSyncRequestMessage _:
- if (!HasComp(uid)) return;
- component.UserInterface?.SendMessage(new LatheFullQueueMessage(GetIdQueue(component)));
- if (component.ProducingRecipe != null)
- component.UserInterface?.SendMessage(new LatheProducingRecipeMessage(component.ProducingRecipe.ID));
- break;
-
- case LatheServerSelectionMessage _:
- if (!TryComp(uid, out ResearchClientComponent? researchClient)) return;
- IoCManager.Resolve()
- .GetEntitySystem()
- .TryOpen(uid, ResearchClientUiKey.Key, message.Session);
- break;
-
- case LatheServerSyncMessage _:
- if (!TryComp(uid, out TechnologyDatabaseComponent? database)
- || !TryComp(uid, out ProtolatheDatabaseComponent? protoDatabase)) return;
-
- if (IoCManager.Resolve().GetEntitySystem().SyncWithServer(database))
- protoDatabase.Sync();
-
- break;
+ // Again: TODO this should be handled by BUI states
+ _uiSys.TrySendUiMessage(uid, LatheUiKey.Key, new LatheFullQueueMessage(component.Queue));
}
+
+ TryStartProducing(component.Owner, null, component);
}
- ///
- /// Gets all the prototypes in the lathe's construction queue
- ///
- private Queue GetIdQueue(LatheComponent lathe)
+ private void OnLatheSyncRequestMessage(EntityUid uid, LatheComponent component, LatheSyncRequestMessage args)
{
- var queue = new Queue();
- foreach (var recipePrototype in lathe.Queue)
- {
- queue.Enqueue(recipePrototype.ID);
- }
- return queue;
+ if (!HasComp(uid)) return;
+
+ // Again: TODO BUI states. Why TF was this was this ever two separate messages!?!?
+ _uiSys.TrySendUiMessage(uid, LatheUiKey.Key, new LatheFullQueueMessage(component.Queue));
+ if (TryComp(uid, out LatheProducingComponent? prodComp) && prodComp.Recipe != null)
+ _uiSys.TrySendUiMessage(uid, LatheUiKey.Key, new LatheProducingRecipeMessage(prodComp.Recipe));
}
+
+ private void OnLatheServerSelectionMessage(EntityUid uid, LatheComponent component, LatheServerSelectionMessage args)
+ {
+ // TODO W.. b.. why?
+ // the client can just open the ui itself. why tf is it asking the server to open it for it.
+ _uiSys.TryOpen(uid, ResearchClientUiKey.Key, (IPlayerSession) args.Session);
+ }
+
+ private void OnLatheServerSyncMessage(EntityUid uid, TechnologyDatabaseComponent component, LatheServerSyncMessage args)
+ {
+ _researchSys.SyncWithServer(component);
+
+ if (TryComp(uid, out ProtolatheDatabaseComponent? protoDatabase))
+ protoDatabase.Sync();
+ }
+
+ #endregion
}
}
diff --git a/Content.Shared/Lathe/LatheMessages.cs b/Content.Shared/Lathe/LatheMessages.cs
index 0ffffb1306..e23bea0ca7 100644
--- a/Content.Shared/Lathe/LatheMessages.cs
+++ b/Content.Shared/Lathe/LatheMessages.cs
@@ -65,8 +65,8 @@ namespace Content.Shared.Lathe;
[Serializable, NetSerializable]
public sealed class LatheFullQueueMessage : BoundUserInterfaceMessage
{
- public readonly Queue Recipes;
- public LatheFullQueueMessage(Queue recipes)
+ public readonly List Recipes;
+ public LatheFullQueueMessage(List recipes)
{
Recipes = recipes;
}