mirror of
https://github.com/wega-team/ss14-wega.git
synced 2026-02-14 19:30:01 +01:00
Fix flatpacker exploit ignoring board costs (#42445)
Fix flatpacks ignoring costs and board requirements
This commit is contained in:
@@ -1,13 +1,11 @@
|
||||
using System.Linq;
|
||||
using Content.Client.Materials;
|
||||
using Content.Client.Materials.UI;
|
||||
using Content.Client.Message;
|
||||
using Content.Client.UserInterface.Controls;
|
||||
using Content.Shared.Construction.Components;
|
||||
using Content.Shared.Containers.ItemSlots;
|
||||
using Content.Shared.Materials;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Timing;
|
||||
@@ -61,57 +59,48 @@ public sealed partial class FlatpackCreatorMenu : FancyWindow
|
||||
!_itemSlots.TryGetSlot(_owner, flatpacker.SlotId, out var itemSlot))
|
||||
return;
|
||||
|
||||
var flatpackerEnt = (_owner, flatpacker);
|
||||
|
||||
if (flatpacker.Packing)
|
||||
{
|
||||
PackButton.Disabled = true;
|
||||
}
|
||||
else if (_currentBoard != null)
|
||||
{
|
||||
Dictionary<string, int> cost;
|
||||
if (_entityManager.TryGetComponent<MachineBoardComponent>(_currentBoard, out var machineBoardComp))
|
||||
cost = _flatpack.GetFlatpackCreationCost((_owner, flatpacker), (_currentBoard.Value, machineBoardComp));
|
||||
else
|
||||
cost = _flatpack.GetFlatpackCreationCost((_owner, flatpacker), null);
|
||||
|
||||
PackButton.Disabled = !_materialStorage.CanChangeMaterialAmount(_owner, cost);
|
||||
PackButton.Disabled = !_flatpack.TryGetFlatpackCreationCost(flatpackerEnt, _currentBoard.Value, out var curCost)
|
||||
|| !_materialStorage.CanChangeMaterialAmount(_owner, curCost);
|
||||
}
|
||||
|
||||
if (_currentBoard == itemSlot.Item)
|
||||
return;
|
||||
|
||||
_currentBoard = itemSlot.Item;
|
||||
CostHeaderLabel.Visible = _currentBoard != null;
|
||||
CostHeaderLabel.Visible = false;
|
||||
InsertLabel.Visible = _currentBoard == null;
|
||||
|
||||
if (_currentBoard is not null)
|
||||
if (_currentBoard is null)
|
||||
{
|
||||
string? prototype = null;
|
||||
Dictionary<string, int>? cost = null;
|
||||
MachineSprite.SetPrototype(NoBoardEffectId);
|
||||
CostLabel.SetMessage(Loc.GetString("flatpacker-ui-no-board-label"));
|
||||
MachineNameLabel.SetMessage(string.Empty);
|
||||
PackButton.Disabled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_entityManager.TryGetComponent<MachineBoardComponent>(_currentBoard, out var newMachineBoardComp))
|
||||
{
|
||||
prototype = newMachineBoardComp.Prototype;
|
||||
cost = _flatpack.GetFlatpackCreationCost((_owner, flatpacker), (_currentBoard.Value, newMachineBoardComp));
|
||||
}
|
||||
else if (_entityManager.TryGetComponent<ComputerBoardComponent>(_currentBoard, out var computerBoard))
|
||||
{
|
||||
prototype = computerBoard.Prototype;
|
||||
cost = _flatpack.GetFlatpackCreationCost((_owner, flatpacker), null);
|
||||
}
|
||||
|
||||
if (prototype is not null && cost is not null)
|
||||
{
|
||||
var proto = _prototypeManager.Index<EntityPrototype>(prototype);
|
||||
MachineSprite.SetPrototype(prototype);
|
||||
MachineNameLabel.SetMessage(proto.Name);
|
||||
CostLabel.SetMarkup(GetCostString(cost));
|
||||
}
|
||||
if (_flatpack.TryGetFlatpackResultPrototype(_currentBoard.Value, out var prototype) &&
|
||||
_flatpack.TryGetFlatpackCreationCost(flatpackerEnt, _currentBoard.Value, out var cost))
|
||||
{
|
||||
var proto = _prototypeManager.Index<EntityPrototype>(prototype);
|
||||
MachineSprite.SetPrototype(prototype);
|
||||
MachineNameLabel.SetMessage(proto.Name);
|
||||
CostLabel.SetMarkup(GetCostString(cost));
|
||||
CostHeaderLabel.Visible = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
MachineSprite.SetPrototype(NoBoardEffectId);
|
||||
CostLabel.SetMessage(Loc.GetString("flatpacker-ui-no-board-label"));
|
||||
MachineNameLabel.SetMessage(" ");
|
||||
CostLabel.SetMarkup(Loc.GetString("flatpacker-ui-board-invalid-label"));
|
||||
MachineNameLabel.SetMessage(string.Empty);
|
||||
PackButton.Disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
using Content.Server.Audio;
|
||||
using Content.Server.Power.Components;
|
||||
using Content.Server.Power.EntitySystems;
|
||||
using Content.Shared.Construction;
|
||||
using Content.Shared.Construction.Components;
|
||||
using Content.Shared.Containers.ItemSlots;
|
||||
using Content.Shared.Power;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Server.Construction;
|
||||
@@ -35,16 +33,8 @@ public sealed class FlatpackSystem : SharedFlatpackSystem
|
||||
if (!_itemSlots.TryGetSlot(uid, comp.SlotId, out var itemSlot) || itemSlot.Item is not { } board)
|
||||
return;
|
||||
|
||||
Dictionary<string, int> cost;
|
||||
if (TryComp<MachineBoardComponent>(board, out var machine))
|
||||
cost = GetFlatpackCreationCost(ent, (board, machine));
|
||||
else if (TryComp<ComputerBoardComponent>(board, out var computer) && computer.Prototype != null)
|
||||
cost = GetFlatpackCreationCost(ent, null);
|
||||
else
|
||||
{
|
||||
Log.Error($"Encountered invalid flatpack board while packing: {ToPrettyString(board)}");
|
||||
if (!TryGetFlatpackCreationCost(ent, board, out var cost))
|
||||
return;
|
||||
}
|
||||
|
||||
if (!MaterialStorage.CanChangeMaterialAmount(uid, cost))
|
||||
return;
|
||||
@@ -80,29 +70,15 @@ public sealed class FlatpackSystem : SharedFlatpackSystem
|
||||
if (!_itemSlots.TryGetSlot(uid, comp.SlotId, out var itemSlot) || itemSlot.Item is not { } board)
|
||||
return;
|
||||
|
||||
Dictionary<string, int> cost;
|
||||
EntProtoId proto;
|
||||
if (TryComp<MachineBoardComponent>(board, out var machine))
|
||||
{
|
||||
cost = GetFlatpackCreationCost(ent, (board, machine));
|
||||
proto = machine.Prototype;
|
||||
}
|
||||
else if (TryComp<ComputerBoardComponent>(board, out var computer) && computer.Prototype != null)
|
||||
{
|
||||
cost = GetFlatpackCreationCost(ent, null);
|
||||
proto = computer.Prototype;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Error($"Encountered invalid flatpack board while packing: {ToPrettyString(board)}");
|
||||
if (!TryGetFlatpackCreationCost(ent, board, out var cost) ||
|
||||
!TryGetFlatpackResultPrototype(board, out var proto))
|
||||
return;
|
||||
}
|
||||
|
||||
if (!MaterialStorage.TryChangeMaterialAmount((ent, null), cost))
|
||||
return;
|
||||
|
||||
var flatpack = Spawn(comp.BaseFlatpackPrototype, Transform(ent).Coordinates);
|
||||
SetupFlatpack(flatpack, proto, board);
|
||||
SetupFlatpack(flatpack, proto.Value, board);
|
||||
Del(board);
|
||||
}
|
||||
|
||||
|
||||
@@ -58,11 +58,11 @@ namespace Content.Shared.Construction
|
||||
}
|
||||
}
|
||||
|
||||
public Dictionary<string, int> GetMachineBoardMaterialCost(Entity<MachineBoardComponent> entity, int coefficient = 1)
|
||||
public bool TryGetMachineBoardMaterialCost(Entity<MachineBoardComponent> entity, out Dictionary<string, int> materials, int coefficient = 1)
|
||||
{
|
||||
var (_, comp) = entity;
|
||||
|
||||
var materials = new Dictionary<string, int>();
|
||||
materials = new Dictionary<string, int>();
|
||||
|
||||
foreach (var (stackId, amount) in comp.StackRequirements)
|
||||
{
|
||||
@@ -89,9 +89,14 @@ namespace Content.Shared.Construction
|
||||
materials[mat] += matAmount * amount * coefficient;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The item has no material cost, so we cannot get the full cost.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
var genericPartInfo = comp.ComponentRequirements.Values.Concat(comp.ComponentRequirements.Values);
|
||||
var genericPartInfo = comp.ComponentRequirements.Values.Concat(comp.TagRequirements.Values);
|
||||
foreach (var info in genericPartInfo)
|
||||
{
|
||||
var amount = info.Amount;
|
||||
@@ -118,9 +123,15 @@ namespace Content.Shared.Construction
|
||||
materials[mat] += matAmount * amount * coefficient;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The item has no material cost, so we cannot get the full cost.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return materials;
|
||||
// We were able to construct all elements of the recipe.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Content.Shared.Construction.Components;
|
||||
using Content.Shared.Administration.Logs;
|
||||
using Content.Shared.Containers.ItemSlots;
|
||||
@@ -125,14 +126,34 @@ public abstract class SharedFlatpackSystem : EntitySystem
|
||||
Appearance.SetData(ent, FlatpackVisuals.Machine, MetaData(board).EntityPrototype?.ID ?? string.Empty);
|
||||
}
|
||||
|
||||
/// <param name="machineBoard">The machine board to pack. If null, this implies we are packing a computer board</param>
|
||||
public Dictionary<string, int> GetFlatpackCreationCost(Entity<FlatpackCreatorComponent> entity, Entity<MachineBoardComponent>? machineBoard)
|
||||
/// <summary>
|
||||
/// Returns the prototype from a board that the flatpacker will create.
|
||||
/// </summary>
|
||||
public bool TryGetFlatpackResultPrototype(EntityUid board, [NotNullWhen(true)] out EntProtoId? prototype)
|
||||
{
|
||||
Dictionary<string, int> cost = new();
|
||||
prototype = null;
|
||||
|
||||
if (TryComp<MachineBoardComponent>(board, out var machine))
|
||||
prototype = machine.Prototype;
|
||||
else if (TryComp<ComputerBoardComponent>(board, out var computer))
|
||||
prototype = computer.Prototype;
|
||||
return prototype is not null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to get the cost to produce an item, fails if unable to produce it.
|
||||
/// </summary>
|
||||
/// <param name="entity">The flatpacking machine</param>
|
||||
/// <param name="machineBoard">The machine board to pack. If null, this implies we are packing a computer board</param>
|
||||
/// <param name="cost">Cost to produce</param>
|
||||
public bool TryGetFlatpackCreationCost(Entity<FlatpackCreatorComponent> entity, EntityUid machineBoard, out Dictionary<string, int> cost)
|
||||
{
|
||||
cost = new();
|
||||
Dictionary<ProtoId<MaterialPrototype>, int> baseCost;
|
||||
if (machineBoard is not null)
|
||||
if (TryComp<MachineBoardComponent>(machineBoard, out var machineBoardComp))
|
||||
{
|
||||
cost = MachinePart.GetMachineBoardMaterialCost(machineBoard.Value, -1);
|
||||
if (!MachinePart.TryGetMachineBoardMaterialCost((machineBoard, machineBoardComp), out cost, -1))
|
||||
return false;
|
||||
baseCost = entity.Comp.BaseMachineCost;
|
||||
}
|
||||
else
|
||||
@@ -144,6 +165,6 @@ public abstract class SharedFlatpackSystem : EntitySystem
|
||||
cost[mat] -= amount;
|
||||
}
|
||||
|
||||
return cost;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,5 +8,7 @@ flatpacker-ui-title = Flatpacker 1001
|
||||
flatpacker-ui-materials-label = Materials
|
||||
flatpacker-ui-cost-label = Packing Cost
|
||||
flatpacker-ui-no-board-label = No board present!
|
||||
flatpacker-ui-board-invalid-label = [color=red]Invalid board!
|
||||
Unable to print![/color]
|
||||
flatpacker-ui-insert-board = Insert a board to begin.
|
||||
flatpacker-ui-pack-button = Pack
|
||||
|
||||
Reference in New Issue
Block a user