Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions Content.Client/Lathe/LatheSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@
using Content.Shared.Power;
using Content.Client.Power;
using Content.Shared.Research.Prototypes;
using Content.Client._Ganimed.Systems; // Ganimed edit
using Content.Shared._Ganimed.Components; // Ganimed edit

namespace Content.Client.Lathe;

public sealed class LatheSystem : SharedLatheSystem
{
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly SpriteSystem _sprite = default!;
[Dependency] private readonly LatheAlertLevelRestrictionSystem _alertLevelRestriction = default!; // Ganimed edit

public override void Initialize()
{
Expand Down Expand Up @@ -57,6 +60,19 @@ protected override bool HasRecipe(EntityUid uid, LatheRecipePrototype recipe, La
{
return true;
}

// Ganimed edit start
public override bool CanProduce(EntityUid uid, LatheRecipePrototype recipe, int amount = 1, LatheComponent? component = null)
{
if (!base.CanProduce(uid, recipe, amount, component))
return false;

if (HasComp<LatheAlertLevelRestrictionComponent>(uid) && !_alertLevelRestriction.IsRecipeAvailable(uid, recipe))
return false;

return true;
}
// Ganimed edit end
}

public enum LatheVisualLayers : byte
Expand Down
16 changes: 16 additions & 0 deletions Content.Client/Lathe/UI/LatheBoundUserInterface.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
using Content.Shared._Ganimed.Components; // Ganimed edit
using Content.Shared.ADT.Salvage; // ADT
using Content.Shared.Lathe;
using Content.Shared.Research.Components;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Client.UserInterface;
using Robust.Shared.IoC;

namespace Content.Client.Lathe.UI
{
Expand All @@ -11,8 +14,12 @@ public sealed class LatheBoundUserInterface : BoundUserInterface
{
[ViewVariables]
private LatheMenu? _menu;

private readonly IEntityManager _entityManager; // Ganimed edit

public LatheBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
{
_entityManager = IoCManager.Resolve<IEntityManager>(); // Ganimed edit
}

protected override void Open()
Expand Down Expand Up @@ -43,7 +50,16 @@ protected override void UpdateState(BoundUserInterfaceState state)
{
case LatheUpdateState msg:
if (_menu != null)
{
_menu.Recipes = msg.Recipes;
// Ganimed edit start

if (_entityManager.TryGetComponent<LatheAlertLevelRestrictionComponent>(Owner, out var restrictionComp))
{
restrictionComp.CurrentAlertLevel = msg.CurrentAlertLevel;
}
}
// Ganimed edit end
_menu?.PopulateRecipes();
_menu?.UpdateCategories();
_menu?.PopulateQueueList(msg.Queue);
Expand Down
46 changes: 43 additions & 3 deletions Content.Client/Lathe/UI/LatheMenu.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,42 @@ private string GenerateTooltipText(LatheRecipePrototype prototype)
StringBuilder sb = new();
var multiplier = _entityManager.GetComponent<LatheComponent>(Entity).MaterialUseMultiplier;

// Ganimed edit start: Show current and required alert level
if (!string.IsNullOrEmpty(prototype.RequiredAlertLevel))
{
// Get required level name
var requiredLevelNameKey = $"lathe-menu-alert-level-{prototype.RequiredAlertLevel}";
var requiredLevelName = Loc.GetString(requiredLevelNameKey);
if (requiredLevelName == requiredLevelNameKey)
{
var alertLevelKey = $"alert-level-{prototype.RequiredAlertLevel}";
requiredLevelName = Loc.GetString(alertLevelKey);
if (requiredLevelName == alertLevelKey)
requiredLevelName = prototype.RequiredAlertLevel;
}

// Get current level name
var currentLevelName = "???";
if (_entityManager.TryGetComponent(Entity, out Content.Shared._Ganimed.Components.LatheAlertLevelRestrictionComponent? restrictionComp)
&& !string.IsNullOrEmpty(restrictionComp.CurrentAlertLevel))
{
var currentLevelNameKey = $"lathe-menu-alert-level-{restrictionComp.CurrentAlertLevel}";
currentLevelName = Loc.GetString(currentLevelNameKey);
if (currentLevelName == currentLevelNameKey)
{
var alertLevelKey = $"alert-level-{restrictionComp.CurrentAlertLevel}";
currentLevelName = Loc.GetString(alertLevelKey);
if (currentLevelName == alertLevelKey)
currentLevelName = restrictionComp.CurrentAlertLevel;
}
}

sb.AppendLine(Loc.GetString("lathe-menu-alert-level-required", ("level", requiredLevelName)));
sb.AppendLine(Loc.GetString("lathe-menu-alert-level-current", ("level", currentLevelName)));
sb.AppendLine();
}
// Ganimed edit end

foreach (var (id, amount) in prototype.Materials)
{
if (!_prototypeManager.TryIndex(id, out var proto))
Expand Down Expand Up @@ -237,7 +273,8 @@ public void UpdateCategories()
var currentCategories = new List<ProtoId<LatheCategoryPrototype>>();
foreach (var recipeId in Recipes)
{
var recipe = _prototypeManager.Index(recipeId);
if (!_prototypeManager.TryIndex(recipeId, out var recipe))
continue;

if (recipe.Categories.Count <= 0)
continue;
Expand Down Expand Up @@ -281,7 +318,9 @@ public void PopulateQueueList(IReadOnlyCollection<ProtoId<LatheRecipePrototype>>
var idx = 1;
foreach (var recipeProto in queue)
{
var recipe = _prototypeManager.Index(recipeProto);
if (!_prototypeManager.TryIndex(recipeProto, out var recipe))
continue;

var queuedRecipeBox = new BoxContainer();
queuedRecipeBox.Orientation = BoxContainer.LayoutOrientation.Horizontal;

Expand All @@ -301,7 +340,8 @@ public void SetQueueInfo(ProtoId<LatheRecipePrototype>? recipeProto)
if (recipeProto == null)
return;

var recipe = _prototypeManager.Index(recipeProto.Value);
if (!_prototypeManager.TryIndex(recipeProto.Value, out var recipe))
return;

FabricatingDisplayContainer.Children.Clear();
FabricatingDisplayContainer.AddChild(GetRecipeDisplayControl(recipe));
Expand Down
8 changes: 8 additions & 0 deletions Content.Client/Lathe/UI/RecipeControl.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@
MinSize="32 32"
/>
<Label Name="RecipeName" HorizontalExpand="True" />
<Label
Name="AlertLevelLockIcon"
Visible="False"
Text="(!)"
FontColorOverride="#DC143C"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Margin="4 0 0 0"/>
</BoxContainer>
</Button>
</Control>
5 changes: 5 additions & 0 deletions Content.Client/Lathe/UI/RecipeControl.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Content.Shared.Research.Prototypes;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls; // Ganimed edit
using Robust.Client.UserInterface.XAML;

namespace Content.Client.Lathe.UI;
Expand All @@ -21,6 +22,10 @@ public RecipeControl(LatheSystem latheSystem, LatheRecipePrototype recipe, Func<
TooltipTextSupplier = tooltipTextSupplier;
Button.TooltipSupplier = SupplyTooltip;

// Ganimed edit start
AlertLevelLockIcon.Visible = recipe.RequiredAlertLevel != null && !canProduce;
// Ganimed edit end

Button.OnPressed += (_) =>
{
OnButtonPressed?.Invoke(recipe.ID);
Expand Down
38 changes: 38 additions & 0 deletions Content.Client/_Ganimed/Systems/ClientAlertLevelHierarchy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
namespace Content.Client._Ganimed.Systems;

/// <summary>
/// Проверка уровней угрозы для клиента.
/// Клиент не имеет доступа к серверным прототипам, поэтому используется фиксированный порядок.
/// ВАЖНО: При изменении порядка в Resources/Prototypes/AlertLevels/alert_levels.yml
/// необходимо обновить этот массив!
/// Порядок: green < blue < violet < yellow < red < gamma < delta < epsilon < amber < altdelta < cascade
/// </summary>
public static class ClientAlertLevelHierarchy
{
/// <summary>
/// Порядок уровней угрозы от наименьшего к наибольшему.
/// ДОЛЖЕН СОВПАДАТЬ с порядком в Resources/Prototypes/AlertLevels/alert_levels.yml
/// </summary>
private static readonly string[] LevelOrder =
{
"green", "blue", "violet", "yellow", "red",
"gamma", "delta", "epsilon", "amber", "altdelta", "cascade"
};

public static bool MeetsAlertLevelRequirement(string? currentLevel, string? requiredLevel)
{
if (string.IsNullOrEmpty(currentLevel) || string.IsNullOrEmpty(requiredLevel))
return false;

if (currentLevel.Equals(requiredLevel, StringComparison.OrdinalIgnoreCase))
return true;

var currentIdx = Array.IndexOf(LevelOrder, currentLevel.ToLower());
var requiredIdx = Array.IndexOf(LevelOrder, requiredLevel.ToLower());

if (currentIdx < 0 || requiredIdx < 0)
return false;

return currentIdx >= requiredIdx;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using Content.Shared.Lathe;
using Content.Shared.Lathe.Prototypes;
using Content.Shared.Research.Prototypes;
using Content.Shared._Ganimed.Components;
using Content.Client._Ganimed.Systems;
using Robust.Client.GameObjects;
using Robust.Shared.Prototypes;

namespace Content.Client._Ganimed.Systems;

public sealed class LatheAlertLevelRestrictionSystem : EntitySystem
{
[Dependency] private readonly IPrototypeManager _proto = default!;

public bool IsRecipeAvailable(EntityUid uid, LatheRecipePrototype recipe, LatheAlertLevelRestrictionComponent? restrictionComp = null)
{
if (!Resolve(uid, ref restrictionComp))
return true;

if (restrictionComp == null)
return true;

if (string.IsNullOrEmpty(recipe.RequiredAlertLevel))
return true;

if (TryComp<ProtolatheEmagComponent>(uid, out var emagComp) && emagComp.IsEmagged)
return true;

if (string.IsNullOrEmpty(restrictionComp.CurrentAlertLevel))
Comment thread
github-code-quality[bot] marked this conversation as resolved.
Fixed
return false;

return ClientAlertLevelHierarchy.MeetsAlertLevelRequirement(restrictionComp.CurrentAlertLevel, recipe.RequiredAlertLevel);
}
}
22 changes: 19 additions & 3 deletions Content.Server/Lathe/LatheSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;
using Content.Shared.DocumentPrinter;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Content.Server._Ganimed.Systems; // Ganimed edit
using Content.Shared._Ganimed.Components; // Ganimed edit

namespace Content.Server.Lathe
{
Expand All @@ -58,6 +59,7 @@ public sealed class LatheSystem : SharedLatheSystem
[Dependency] private readonly StackSystem _stack = default!;
[Dependency] private readonly TransformSystem _transform = default!;
[Dependency] private readonly RadioSystem _radio = default!;
[Dependency] private readonly LatheAlertLevelRestrictionSystem _alertLevelRestriction = default!; // Ganimed edit

/// <summary>
/// Per-tick cache
Expand Down Expand Up @@ -174,6 +176,11 @@ public bool TryAddToQueue(EntityUid uid, LatheRecipePrototype recipe, LatheCompo
if (!Resolve(uid, ref component))
return false;

// Ganimed edit start: Check alert level restriction
if (!_alertLevelRestriction.IsRecipeAvailable(uid, recipe))
return false;
// Ganimed edit end

if (!CanProduce(uid, recipe, 1, component))
return false;

Expand All @@ -198,7 +205,8 @@ public bool TryStartProducing(EntityUid uid, LatheComponent? component = null)
return false;

var recipeProto = component.Queue.Dequeue();
var recipe = _proto.Index(recipeProto);
if (!_proto.TryIndex(recipeProto, out var recipe))
return false; // Recipe prototype not found, skip it

var time = _reagentSpeed.ApplySpeed(uid, recipe.CompleteTime) * component.TimeMultiplier;

Expand Down Expand Up @@ -288,7 +296,15 @@ public void UpdateUserInterfaceState(EntityUid uid, LatheComponent? component =
if (producing == null && component.Queue.TryPeek(out var next))
producing = next;

var state = new LatheUpdateState(GetAvailableRecipes(uid, component), component.Queue.ToArray(), producing);
// Ganimed edit start
string? currentAlertLevel = null;
if (TryComp<LatheAlertLevelRestrictionComponent>(uid, out var restrictionComp))
{
currentAlertLevel = restrictionComp.CurrentAlertLevel;
}
// Ganimed edit end

var state = new LatheUpdateState(GetAvailableRecipes(uid, component), component.Queue.ToArray(), producing, currentAlertLevel); // Ganimed edit
_uiSys.SetUiState(uid, LatheUiKey.Key, state);
}

Expand Down
37 changes: 37 additions & 0 deletions Content.Server/_Ganimed/Systems/AlertLevelHierarchy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System.Linq;
using Robust.Shared.IoC;
using Robust.Shared.Prototypes;
using Content.Server.AlertLevel;

namespace Content.Server._Ganimed.Systems;
public static class AlertLevelHierarchy
{
public static bool MeetsAlertLevelRequirement(
string? currentLevel,
string? requiredLevel,
IPrototypeManager? prototypeManager = null)
{
if (string.IsNullOrEmpty(currentLevel) || string.IsNullOrEmpty(requiredLevel))
return false;

if (currentLevel.Equals(requiredLevel, StringComparison.OrdinalIgnoreCase))
return true;

if (prototypeManager == null)
prototypeManager = IoCManager.Resolve<IPrototypeManager>();

if (!prototypeManager.TryIndex<AlertLevelPrototype>("stationAlerts", out var alertPrototype))
return false;

var levels = alertPrototype.Levels.Keys.ToList();


var currentIdx = levels.FindIndex(l => l.Equals(currentLevel, StringComparison.OrdinalIgnoreCase));
var requiredIdx = levels.FindIndex(l => l.Equals(requiredLevel, StringComparison.OrdinalIgnoreCase));

if (currentIdx < 0 || requiredIdx < 0)
return false;

return currentIdx >= requiredIdx;
}
}
Loading