Batchable lathe jobs, editable lathe job order (#38624)
* batchable lathe jobs, editable order * requested changes * LatheComponent comment, menu strings
This commit is contained in:
@@ -30,6 +30,10 @@ namespace Content.Client.Lathe.UI
|
||||
{
|
||||
SendMessage(new LatheQueueRecipeMessage(recipe, amount));
|
||||
};
|
||||
_menu.QueueDeleteAction += index => SendMessage(new LatheDeleteRequestMessage(index));
|
||||
_menu.QueueMoveUpAction += index => SendMessage(new LatheMoveRequestMessage(index, -1));
|
||||
_menu.QueueMoveDownAction += index => SendMessage(new LatheMoveRequestMessage(index, 1));
|
||||
_menu.DeleteFabricatingAction += () => SendMessage(new LatheAbortFabricationMessage());
|
||||
}
|
||||
|
||||
protected override void UpdateState(BoundUserInterfaceState state)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<DefaultWindow
|
||||
xmlns="https://spacestation14.io"
|
||||
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
|
||||
xmlns:system="clr-namespace:System;assembly=System.Runtime"
|
||||
xmlns:ui="clr-namespace:Content.Client.Materials.UI"
|
||||
Title="{Loc 'lathe-menu-title'}"
|
||||
MinSize="550 450"
|
||||
@@ -110,6 +111,18 @@
|
||||
HorizontalAlignment="Left"
|
||||
Margin="130 0 0 0">
|
||||
</Label>
|
||||
<Button
|
||||
Name="DeleteFabricating"
|
||||
Margin="0"
|
||||
Text="✖"
|
||||
SetSize="38 32"
|
||||
HorizontalAlignment="Right"
|
||||
ToolTip="{Loc 'lathe-menu-delete-fabricating-tooltip'}">
|
||||
<Button.StyleClasses>
|
||||
<system:String>Caution</system:String>
|
||||
<system:String>OpenLeft</system:String>
|
||||
</Button.StyleClasses>
|
||||
</Button>
|
||||
</PanelContainer>
|
||||
</BoxContainer>
|
||||
<ScrollContainer VerticalExpand="True" HScrollEnabled="False">
|
||||
|
||||
@@ -26,6 +26,10 @@ public sealed partial class LatheMenu : DefaultWindow
|
||||
|
||||
public event Action<BaseButton.ButtonEventArgs>? OnServerListButtonPressed;
|
||||
public event Action<string, int>? RecipeQueueAction;
|
||||
public event Action<int>? QueueDeleteAction;
|
||||
public event Action<int>? QueueMoveUpAction;
|
||||
public event Action<int>? QueueMoveDownAction;
|
||||
public event Action? DeleteFabricatingAction;
|
||||
|
||||
public List<ProtoId<LatheRecipePrototype>> Recipes = new();
|
||||
|
||||
@@ -50,12 +54,21 @@ public sealed partial class LatheMenu : DefaultWindow
|
||||
};
|
||||
AmountLineEdit.OnTextChanged += _ =>
|
||||
{
|
||||
if (int.TryParse(AmountLineEdit.Text, out var amount))
|
||||
{
|
||||
if (amount > LatheSystem.MaxItemsPerRequest)
|
||||
AmountLineEdit.Text = LatheSystem.MaxItemsPerRequest.ToString();
|
||||
else if (amount < 0)
|
||||
AmountLineEdit.Text = "0";
|
||||
}
|
||||
|
||||
PopulateRecipes();
|
||||
};
|
||||
|
||||
FilterOption.OnItemSelected += OnItemSelected;
|
||||
|
||||
ServerListButton.OnPressed += a => OnServerListButtonPressed?.Invoke(a);
|
||||
DeleteFabricating.OnPressed += _ => DeleteFabricatingAction?.Invoke();
|
||||
}
|
||||
|
||||
public void SetEntity(EntityUid uid)
|
||||
@@ -223,22 +236,27 @@ public sealed partial class LatheMenu : DefaultWindow
|
||||
/// Populates the build queue list with all queued items
|
||||
/// </summary>
|
||||
/// <param name="queue"></param>
|
||||
public void PopulateQueueList(IReadOnlyCollection<ProtoId<LatheRecipePrototype>> queue)
|
||||
public void PopulateQueueList(IReadOnlyCollection<LatheRecipeBatch> queue)
|
||||
{
|
||||
QueueList.DisposeAllChildren();
|
||||
|
||||
var idx = 1;
|
||||
foreach (var recipeProto in queue)
|
||||
foreach (var batch in queue)
|
||||
{
|
||||
var recipe = _prototypeManager.Index(recipeProto);
|
||||
var queuedRecipeBox = new BoxContainer();
|
||||
queuedRecipeBox.Orientation = BoxContainer.LayoutOrientation.Horizontal;
|
||||
var recipe = _prototypeManager.Index(batch.Recipe);
|
||||
|
||||
queuedRecipeBox.AddChild(GetRecipeDisplayControl(recipe));
|
||||
var itemName = _lathe.GetRecipeName(batch.Recipe);
|
||||
string displayText;
|
||||
if (batch.ItemsRequested > 1)
|
||||
displayText = Loc.GetString("lathe-menu-item-batch", ("index", idx), ("name", itemName), ("printed", batch.ItemsPrinted), ("total", batch.ItemsRequested));
|
||||
else
|
||||
displayText = Loc.GetString("lathe-menu-item-single", ("index", idx), ("name", itemName));
|
||||
|
||||
var queuedRecipeBox = new QueuedRecipeControl(displayText, idx - 1, GetRecipeDisplayControl(recipe));
|
||||
queuedRecipeBox.OnDeletePressed += s => QueueDeleteAction?.Invoke(s);
|
||||
queuedRecipeBox.OnMoveUpPressed += s => QueueMoveUpAction?.Invoke(s);
|
||||
queuedRecipeBox.OnMoveDownPressed += s => QueueMoveDownAction?.Invoke(s);
|
||||
|
||||
var queuedRecipeLabel = new Label();
|
||||
queuedRecipeLabel.Text = $"{idx}. {_lathe.GetRecipeName(recipe)}";
|
||||
queuedRecipeBox.AddChild(queuedRecipeLabel);
|
||||
QueueList.AddChild(queuedRecipeBox);
|
||||
idx++;
|
||||
}
|
||||
|
||||
35
Content.Client/Lathe/UI/QueuedRecipeControl.xaml
Normal file
35
Content.Client/Lathe/UI/QueuedRecipeControl.xaml
Normal file
@@ -0,0 +1,35 @@
|
||||
<Control xmlns="https://spacestation14.io"
|
||||
xmlns:system="clr-namespace:System;assembly=System.Runtime">
|
||||
<BoxContainer Orientation="Horizontal">
|
||||
<BoxContainer
|
||||
Name="RecipeDisplayContainer"
|
||||
Margin="0 0 4 0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
MinSize="32 32"
|
||||
/>
|
||||
<Label Name="RecipeName" HorizontalExpand="True" />
|
||||
<Button
|
||||
Name="MoveUp"
|
||||
Margin="0"
|
||||
Text="⏶"
|
||||
StyleClasses="OpenRight"
|
||||
ToolTip="{Loc 'lathe-menu-move-up-tooltip'}"/>
|
||||
<Button
|
||||
Name="MoveDown"
|
||||
Margin="0"
|
||||
Text="⏷"
|
||||
StyleClasses="OpenBoth"
|
||||
ToolTip="{Loc 'lathe-menu-move-down-tooltip'}"/>
|
||||
<Button
|
||||
Name="Delete"
|
||||
Margin="0"
|
||||
Text="✖"
|
||||
ToolTip="{Loc 'lathe-menu-delete-item-tooltip'}">
|
||||
<Button.StyleClasses>
|
||||
<system:String>Caution</system:String>
|
||||
<system:String>OpenLeft</system:String>
|
||||
</Button.StyleClasses>
|
||||
</Button>
|
||||
</BoxContainer>
|
||||
</Control>
|
||||
36
Content.Client/Lathe/UI/QueuedRecipeControl.xaml.cs
Normal file
36
Content.Client/Lathe/UI/QueuedRecipeControl.xaml.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
|
||||
namespace Content.Client.Lathe.UI;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class QueuedRecipeControl : Control
|
||||
{
|
||||
public Action<int>? OnDeletePressed;
|
||||
public Action<int>? OnMoveUpPressed;
|
||||
public Action<int>? OnMoveDownPressed;
|
||||
|
||||
public QueuedRecipeControl(string displayText, int index, Control displayControl)
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
|
||||
RecipeName.Text = displayText;
|
||||
RecipeDisplayContainer.AddChild(displayControl);
|
||||
|
||||
MoveUp.OnPressed += (_) =>
|
||||
{
|
||||
OnMoveUpPressed?.Invoke(index);
|
||||
};
|
||||
|
||||
MoveDown.OnPressed += (_) =>
|
||||
{
|
||||
OnMoveDownPressed?.Invoke(index);
|
||||
};
|
||||
|
||||
Delete.OnPressed += (_) =>
|
||||
{
|
||||
OnDeletePressed?.Invoke(index);
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -74,6 +74,9 @@ namespace Content.Server.Lathe
|
||||
|
||||
SubscribeLocalEvent<LatheComponent, LatheQueueRecipeMessage>(OnLatheQueueRecipeMessage);
|
||||
SubscribeLocalEvent<LatheComponent, LatheSyncRequestMessage>(OnLatheSyncRequestMessage);
|
||||
SubscribeLocalEvent<LatheComponent, LatheDeleteRequestMessage>(OnLatheDeleteRequestMessage);
|
||||
SubscribeLocalEvent<LatheComponent, LatheMoveRequestMessage>(OnLatheMoveRequestMessage);
|
||||
SubscribeLocalEvent<LatheComponent, LatheAbortFabricationMessage>(OnLatheAbortFabricationMessage);
|
||||
|
||||
SubscribeLocalEvent<LatheComponent, BeforeActivatableUIOpenEvent>((u, c, _) => UpdateUserInterfaceState(u, c));
|
||||
SubscribeLocalEvent<LatheComponent, MaterialAmountChangedEvent>(OnMaterialAmountChanged);
|
||||
@@ -167,23 +170,32 @@ namespace Content.Server.Lathe
|
||||
return ev.Recipes.ToList();
|
||||
}
|
||||
|
||||
public bool TryAddToQueue(EntityUid uid, LatheRecipePrototype recipe, LatheComponent? component = null)
|
||||
public bool TryAddToQueue(EntityUid uid, LatheRecipePrototype recipe, int quantity, LatheComponent? component = null)
|
||||
{
|
||||
if (!Resolve(uid, ref component))
|
||||
return false;
|
||||
|
||||
if (!CanProduce(uid, recipe, 1, component))
|
||||
if (quantity <= 0)
|
||||
return false;
|
||||
quantity = int.Min(quantity, MaxItemsPerRequest);
|
||||
|
||||
if (!CanProduce(uid, recipe, quantity, component))
|
||||
return false;
|
||||
|
||||
foreach (var (mat, amount) in recipe.Materials)
|
||||
{
|
||||
var adjustedAmount = recipe.ApplyMaterialDiscount
|
||||
? (int) (-amount * component.MaterialUseMultiplier)
|
||||
? (int)(-amount * component.MaterialUseMultiplier)
|
||||
: -amount;
|
||||
adjustedAmount *= quantity;
|
||||
|
||||
_materialStorage.TryChangeMaterialAmount(uid, mat, adjustedAmount);
|
||||
}
|
||||
component.Queue.Enqueue(recipe);
|
||||
|
||||
if (component.Queue.Last is { } node && node.ValueRef.Recipe == recipe.ID)
|
||||
node.ValueRef.ItemsRequested += quantity;
|
||||
else
|
||||
component.Queue.AddLast(new LatheRecipeBatch(recipe.ID, 0, quantity));
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -195,8 +207,11 @@ namespace Content.Server.Lathe
|
||||
if (component.CurrentRecipe != null || component.Queue.Count <= 0 || !this.IsPowered(uid, EntityManager))
|
||||
return false;
|
||||
|
||||
var recipeProto = component.Queue.Dequeue();
|
||||
var recipe = _proto.Index(recipeProto);
|
||||
var batch = component.Queue.First();
|
||||
batch.ItemsPrinted++;
|
||||
if (batch.ItemsPrinted >= batch.ItemsRequested || batch.ItemsPrinted < 0) // Rollover sanity check
|
||||
component.Queue.RemoveFirst();
|
||||
var recipe = _proto.Index(batch.Recipe);
|
||||
|
||||
var time = _reagentSpeed.ApplySpeed(uid, recipe.CompleteTime) * component.TimeMultiplier;
|
||||
|
||||
@@ -271,8 +286,8 @@ namespace Content.Server.Lathe
|
||||
return;
|
||||
|
||||
var producing = component.CurrentRecipe;
|
||||
if (producing == null && component.Queue.TryPeek(out var next))
|
||||
producing = next;
|
||||
if (producing == null && component.Queue.First is { } node)
|
||||
producing = node.Value.Recipe;
|
||||
|
||||
var state = new LatheUpdateState(GetAvailableRecipes(uid, component), component.Queue.ToArray(), producing);
|
||||
_uiSys.SetUiState(uid, LatheUiKey.Key, state);
|
||||
@@ -349,12 +364,10 @@ namespace Content.Server.Lathe
|
||||
{
|
||||
if (!args.Powered)
|
||||
{
|
||||
RemComp<LatheProducingComponent>(uid);
|
||||
UpdateRunningAppearance(uid, false);
|
||||
AbortProduction(uid);
|
||||
}
|
||||
else if (component.CurrentRecipe != null)
|
||||
else
|
||||
{
|
||||
EnsureComp<LatheProducingComponent>(uid);
|
||||
TryStartProducing(uid, component);
|
||||
}
|
||||
}
|
||||
@@ -416,25 +429,46 @@ namespace Content.Server.Lathe
|
||||
return GetAvailableRecipes(uid, component).Contains(recipe.ID);
|
||||
}
|
||||
|
||||
public void AbortProduction(EntityUid uid, LatheComponent? component = null)
|
||||
{
|
||||
if (!Resolve(uid, ref component))
|
||||
return;
|
||||
|
||||
if (component.CurrentRecipe != null)
|
||||
{
|
||||
if (component.Queue.Count > 0)
|
||||
{
|
||||
// Batch abandoned while printing last item, need to create a one-item batch
|
||||
var batch = component.Queue.First();
|
||||
if (batch.Recipe != component.CurrentRecipe)
|
||||
{
|
||||
var newBatch = new LatheRecipeBatch(component.CurrentRecipe.Value, 0, 1);
|
||||
component.Queue.AddFirst(newBatch);
|
||||
}
|
||||
else if (batch.ItemsPrinted > 0)
|
||||
{
|
||||
batch.ItemsPrinted--;
|
||||
}
|
||||
}
|
||||
|
||||
component.CurrentRecipe = null;
|
||||
}
|
||||
RemCompDeferred<LatheProducingComponent>(uid);
|
||||
UpdateUserInterfaceState(uid, component);
|
||||
UpdateRunningAppearance(uid, false);
|
||||
}
|
||||
|
||||
#region UI Messages
|
||||
|
||||
private void OnLatheQueueRecipeMessage(EntityUid uid, LatheComponent component, LatheQueueRecipeMessage args)
|
||||
{
|
||||
if (_proto.TryIndex(args.ID, out LatheRecipePrototype? recipe))
|
||||
{
|
||||
var count = 0;
|
||||
for (var i = 0; i < args.Quantity; i++)
|
||||
{
|
||||
if (TryAddToQueue(uid, recipe, component))
|
||||
count++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (count > 0)
|
||||
if (TryAddToQueue(uid, recipe, args.Quantity, component))
|
||||
{
|
||||
_adminLogger.Add(LogType.Action,
|
||||
LogImpact.Low,
|
||||
$"{ToPrettyString(args.Actor):player} queued {count} {GetRecipeName(recipe)} at {ToPrettyString(uid):lathe}");
|
||||
$"{ToPrettyString(args.Actor):player} queued {args.Quantity} {GetRecipeName(recipe)} at {ToPrettyString(uid):lathe}");
|
||||
}
|
||||
}
|
||||
TryStartProducing(uid, component);
|
||||
@@ -445,6 +479,92 @@ namespace Content.Server.Lathe
|
||||
{
|
||||
UpdateUserInterfaceState(uid, component);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a batch from the batch queue by index.
|
||||
/// If the index given does not exist or is outside of the bounds of the lathe's batch queue, nothing happens.
|
||||
/// </summary>
|
||||
/// <param name="uid">The lathe whose queue is being altered.</param>
|
||||
/// <param name="component"></param>
|
||||
/// <param name="args"></param>
|
||||
public void OnLatheDeleteRequestMessage(EntityUid uid, LatheComponent component, ref LatheDeleteRequestMessage args)
|
||||
{
|
||||
if (args.Index < 0 || args.Index >= component.Queue.Count)
|
||||
return;
|
||||
|
||||
var node = component.Queue.First;
|
||||
for (int i = 0; i < args.Index; i++)
|
||||
node = node?.Next;
|
||||
|
||||
if (node == null) // Shouldn't happen with checks above.
|
||||
return;
|
||||
|
||||
var batch = node.Value;
|
||||
_adminLogger.Add(LogType.Action,
|
||||
LogImpact.Low,
|
||||
$"{ToPrettyString(args.Actor):player} deleted a lathe job for ({batch.ItemsPrinted}/{batch.ItemsRequested}) {GetRecipeName(batch.Recipe)} at {ToPrettyString(uid):lathe}");
|
||||
|
||||
component.Queue.Remove(node);
|
||||
UpdateUserInterfaceState(uid, component);
|
||||
}
|
||||
|
||||
public void OnLatheMoveRequestMessage(EntityUid uid, LatheComponent component, ref LatheMoveRequestMessage args)
|
||||
{
|
||||
if (args.Change == 0 || args.Index < 0 || args.Index >= component.Queue.Count)
|
||||
return;
|
||||
|
||||
// New index must be within the bounds of the batch.
|
||||
var newIndex = args.Index + args.Change;
|
||||
if (newIndex < 0 || newIndex >= component.Queue.Count)
|
||||
return;
|
||||
|
||||
var node = component.Queue.First;
|
||||
for (int i = 0; i < args.Index; i++)
|
||||
node = node?.Next;
|
||||
|
||||
if (node == null) // Something went wrong.
|
||||
return;
|
||||
|
||||
if (args.Change > 0)
|
||||
{
|
||||
var newRelativeNode = node.Next;
|
||||
for (int i = 1; i < args.Change; i++) // 1-indexed: starting from Next
|
||||
newRelativeNode = newRelativeNode?.Next;
|
||||
|
||||
if (newRelativeNode == null) // Something went wrong.
|
||||
return;
|
||||
|
||||
component.Queue.Remove(node);
|
||||
component.Queue.AddAfter(newRelativeNode, node);
|
||||
}
|
||||
else
|
||||
{
|
||||
var newRelativeNode = node.Previous;
|
||||
for (int i = 1; i < -args.Change; i++) // 1-indexed: starting from Previous
|
||||
newRelativeNode = newRelativeNode?.Previous;
|
||||
|
||||
if (newRelativeNode == null) // Something went wrong.
|
||||
return;
|
||||
|
||||
component.Queue.Remove(node);
|
||||
component.Queue.AddBefore(newRelativeNode, node);
|
||||
}
|
||||
|
||||
UpdateUserInterfaceState(uid, component);
|
||||
}
|
||||
|
||||
public void OnLatheAbortFabricationMessage(EntityUid uid, LatheComponent component, ref LatheAbortFabricationMessage args)
|
||||
{
|
||||
if (component.CurrentRecipe == null)
|
||||
return;
|
||||
|
||||
_adminLogger.Add(LogType.Action,
|
||||
LogImpact.Low,
|
||||
$"{ToPrettyString(args.Actor):player} aborted printing {GetRecipeName(component.CurrentRecipe.Value)} at {ToPrettyString(uid):lathe}");
|
||||
|
||||
component.CurrentRecipe = null;
|
||||
FinishProducing(uid, component);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,10 +26,14 @@ namespace Content.Shared.Lathe
|
||||
// Otherwise the material arbitrage test and/or LatheSystem.GetAllBaseRecipes needs to be updated
|
||||
|
||||
/// <summary>
|
||||
/// The lathe's construction queue
|
||||
/// The lathe's construction queue.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is a LinkedList to allow for constant time insertion/deletion (vs a List), and more efficient
|
||||
/// moves (vs a Queue).
|
||||
/// </remarks>
|
||||
[DataField]
|
||||
public Queue<ProtoId<LatheRecipePrototype>> Queue = new();
|
||||
public LinkedList<LatheRecipeBatch> Queue = new();
|
||||
|
||||
/// <summary>
|
||||
/// The sound that plays when the lathe is producing an item, if any
|
||||
@@ -97,6 +101,21 @@ namespace Content.Shared.Lathe
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public sealed partial class LatheRecipeBatch
|
||||
{
|
||||
public ProtoId<LatheRecipePrototype> Recipe;
|
||||
public int ItemsPrinted;
|
||||
public int ItemsRequested;
|
||||
|
||||
public LatheRecipeBatch(ProtoId<LatheRecipePrototype> recipe, int itemsPrinted, int itemsRequested)
|
||||
{
|
||||
Recipe = recipe;
|
||||
ItemsPrinted = itemsPrinted;
|
||||
ItemsRequested = itemsRequested;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event raised on a lathe when it starts producing a recipe.
|
||||
/// </summary>
|
||||
|
||||
@@ -10,11 +10,11 @@ public sealed class LatheUpdateState : BoundUserInterfaceState
|
||||
{
|
||||
public List<ProtoId<LatheRecipePrototype>> Recipes;
|
||||
|
||||
public ProtoId<LatheRecipePrototype>[] Queue;
|
||||
public LatheRecipeBatch[] Queue;
|
||||
|
||||
public ProtoId<LatheRecipePrototype>? CurrentlyProducing;
|
||||
|
||||
public LatheUpdateState(List<ProtoId<LatheRecipePrototype>> recipes, ProtoId<LatheRecipePrototype>[] queue, ProtoId<LatheRecipePrototype>? currentlyProducing = null)
|
||||
public LatheUpdateState(List<ProtoId<LatheRecipePrototype>> recipes, LatheRecipeBatch[] queue, ProtoId<LatheRecipePrototype>? currentlyProducing = null)
|
||||
{
|
||||
Recipes = recipes;
|
||||
Queue = queue;
|
||||
@@ -46,6 +46,33 @@ public sealed class LatheQueueRecipeMessage : BoundUserInterfaceMessage
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sent to the server to remove a batch from the queue.
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class LatheDeleteRequestMessage(int index) : BoundUserInterfaceMessage
|
||||
{
|
||||
public int Index = index;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sent to the server to move the position of a batch in the queue.
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class LatheMoveRequestMessage(int index, int change) : BoundUserInterfaceMessage
|
||||
{
|
||||
public int Index = index;
|
||||
public int Change = change;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sent to the server to stop producing the current item.
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class LatheAbortFabricationMessage() : BoundUserInterfaceMessage
|
||||
{
|
||||
}
|
||||
|
||||
[NetSerializable, Serializable]
|
||||
public enum LatheUiKey
|
||||
{
|
||||
|
||||
81
Content.Shared/Lathe/PrototypeIdLinkedListSerializer.cs
Normal file
81
Content.Shared/Lathe/PrototypeIdLinkedListSerializer.cs
Normal file
@@ -0,0 +1,81 @@
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.Manager;
|
||||
using Robust.Shared.Serialization.Markdown;
|
||||
using Robust.Shared.Serialization.Markdown.Sequence;
|
||||
using Robust.Shared.Serialization.Markdown.Validation;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Interfaces;
|
||||
|
||||
namespace Content.Shared.Lathe;
|
||||
|
||||
/// <summary>
|
||||
/// Handles reading, writing, and validation for linked lists of prototypes.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of prototype this linked list represents</typeparam>
|
||||
/// <remarks>
|
||||
/// This is in the Content.Shared.Lathe namespace as there are no other LinkedList ProtoId instances.
|
||||
/// </remarks>
|
||||
[TypeSerializer]
|
||||
public sealed class LinkedListSerializer<T> : ITypeSerializer<LinkedList<T>, SequenceDataNode>, ITypeCopier<LinkedList<T>> where T : class
|
||||
{
|
||||
public ValidationNode Validate(ISerializationManager serializationManager, SequenceDataNode node,
|
||||
IDependencyCollection dependencies, ISerializationContext? context = null)
|
||||
{
|
||||
var list = new List<ValidationNode>();
|
||||
|
||||
foreach (var elem in node.Sequence)
|
||||
{
|
||||
list.Add(serializationManager.ValidateNode<T>(elem, context));
|
||||
}
|
||||
|
||||
return new ValidatedSequenceNode(list);
|
||||
}
|
||||
|
||||
public DataNode Write(ISerializationManager serializationManager, LinkedList<T> value,
|
||||
IDependencyCollection dependencies,
|
||||
bool alwaysWrite = false,
|
||||
ISerializationContext? context = null)
|
||||
{
|
||||
var sequence = new SequenceDataNode();
|
||||
|
||||
foreach (var elem in value)
|
||||
{
|
||||
sequence.Add(serializationManager.WriteValue(elem, alwaysWrite, context));
|
||||
}
|
||||
|
||||
return sequence;
|
||||
}
|
||||
|
||||
LinkedList<T> ITypeReader<LinkedList<T>, SequenceDataNode>.Read(ISerializationManager serializationManager,
|
||||
SequenceDataNode node,
|
||||
IDependencyCollection dependencies,
|
||||
SerializationHookContext hookCtx,
|
||||
ISerializationContext? context, ISerializationManager.InstantiationDelegate<LinkedList<T>>? instanceProvider)
|
||||
{
|
||||
var list = instanceProvider != null ? instanceProvider() : new LinkedList<T>();
|
||||
|
||||
foreach (var dataNode in node.Sequence)
|
||||
{
|
||||
list.AddLast(serializationManager.Read<T>(dataNode, hookCtx, context));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public void CopyTo(
|
||||
ISerializationManager serializationManager,
|
||||
LinkedList<T> source,
|
||||
ref LinkedList<T> target,
|
||||
IDependencyCollection dependencies,
|
||||
SerializationHookContext hookCtx,
|
||||
ISerializationContext? context = null)
|
||||
{
|
||||
target.Clear();
|
||||
using var enumerator = source.GetEnumerator();
|
||||
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
var current = enumerator.Current;
|
||||
target.AddLast(current);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@ public abstract class SharedLatheSystem : EntitySystem
|
||||
[Dependency] private readonly EmagSystem _emag = default!;
|
||||
|
||||
public readonly Dictionary<string, List<LatheRecipePrototype>> InverseRecipes = new();
|
||||
public const int MaxItemsPerRequest = 10_000;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -86,6 +87,8 @@ public abstract class SharedLatheSystem : EntitySystem
|
||||
return false;
|
||||
if (!HasRecipe(uid, recipe, component))
|
||||
return false;
|
||||
if (amount <= 0)
|
||||
return false;
|
||||
|
||||
foreach (var (material, needed) in recipe.Materials)
|
||||
{
|
||||
|
||||
@@ -29,3 +29,9 @@ lathe-menu-silo-linked-message = Silo Linked
|
||||
lathe-menu-fabricating-message = Fabricating...
|
||||
lathe-menu-materials-title = Materials
|
||||
lathe-menu-queue-title = Build Queue
|
||||
lathe-menu-delete-fabricating-tooltip = Cancel printing the current item.
|
||||
lathe-menu-delete-item-tooltip = Cancel printing this batch.
|
||||
lathe-menu-move-up-tooltip = Move this batch ahead in the queue.
|
||||
lathe-menu-move-down-tooltip = Move this batch back in the queue.
|
||||
lathe-menu-item-single = {$index}. {$name}
|
||||
lathe-menu-item-batch = {$index}. {$name} ({$printed}/{$total})
|
||||
|
||||
Reference in New Issue
Block a user