diff --git a/.editorconfig b/.editorconfig index a5dfab07a503..1583c600aa56 100644 --- a/.editorconfig +++ b/.editorconfig @@ -129,7 +129,7 @@ csharp_indent_braces = false csharp_indent_switch_labels = true # Space preferences -csharp_space_after_cast = true +csharp_space_after_cast = false csharp_space_after_colon_in_inheritance_clause = true csharp_space_after_comma = true csharp_space_after_dot = false diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index da9d4d693a81..2b6d556117ef 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -55,3 +55,10 @@ #Jezi /Content.*/Medical @Jezithyr /Content.*/Body @Jezithyr + +# Sloth +/Content.*/Audio @metalgearsloth +/Content.*/Movement @metalgearsloth +/Content.*/NPC @metalgearsloth +/Content.*/Shuttles @metalgearsloth +/Content.*/Weapons @metalgearsloth diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index d3086cbdd212..e37631903e4b 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -30,7 +30,7 @@ --> update visuals. - if (Container.TryGetContainingContainer(uid, out var container)) + if (Container.TryGetContainingContainer((uid, null, null), out var container)) RaiseLocalEvent(container.Owner, new VisualsChangedEvent(GetNetEntity(uid), container.ID)); } diff --git a/Content.Client/Items/Systems/ItemToggleSystem.cs b/Content.Client/Items/Systems/ItemToggleSystem.cs deleted file mode 100644 index 46d6f1b464d3..000000000000 --- a/Content.Client/Items/Systems/ItemToggleSystem.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Content.Shared.Item.ItemToggle; - -namespace Content.Shared.Item; - -/// -public sealed class ItemToggleSystem : SharedItemToggleSystem -{ - -} diff --git a/Content.Client/Jittering/JitteringSystem.cs b/Content.Client/Jittering/JitteringSystem.cs index 185bd490d3b1..0c11a1396355 100644 --- a/Content.Client/Jittering/JitteringSystem.cs +++ b/Content.Client/Jittering/JitteringSystem.cs @@ -48,6 +48,9 @@ private void OnAnimationCompleted(EntityUid uid, JitteringComponent jittering, A if(args.Key != _jitterAnimationKey) return; + if (!args.Finished) + return; + if (TryComp(uid, out AnimationPlayerComponent? animationPlayer) && TryComp(uid, out SpriteComponent? sprite)) _animationPlayer.Play(uid, animationPlayer, GetAnimation(jittering, sprite), _jitterAnimationKey); diff --git a/Content.Client/Kitchen/UI/GrinderMenu.xaml.cs b/Content.Client/Kitchen/UI/GrinderMenu.xaml.cs index f97d8a733021..7884268c4285 100644 --- a/Content.Client/Kitchen/UI/GrinderMenu.xaml.cs +++ b/Content.Client/Kitchen/UI/GrinderMenu.xaml.cs @@ -12,42 +12,34 @@ namespace Content.Client.Kitchen.UI [GenerateTypedNameReferences] public sealed partial class GrinderMenu : FancyWindow { - private readonly IEntityManager _entityManager; - private readonly IPrototypeManager _prototypeManager; - private readonly ReagentGrinderBoundUserInterface _owner; + [Dependency] private readonly IEntityManager _entityManager = default!; + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; private readonly Dictionary _chamberVisualContents = new(); - public GrinderMenu(ReagentGrinderBoundUserInterface owner, IEntityManager entityManager, IPrototypeManager prototypeManager) + public event Action? OnToggleAuto; + public event Action? OnGrind; + public event Action? OnJuice; + public event Action? OnEjectAll; + public event Action? OnEjectBeaker; + public event Action? OnEjectChamber; + + public GrinderMenu() { RobustXamlLoader.Load(this); - _entityManager = entityManager; - _prototypeManager = prototypeManager; - _owner = owner; - AutoModeButton.OnPressed += owner.ToggleAutoMode; - GrindButton.OnPressed += owner.StartGrinding; - JuiceButton.OnPressed += owner.StartJuicing; - ChamberContentBox.EjectButton.OnPressed += owner.EjectAll; - BeakerContentBox.EjectButton.OnPressed += owner.EjectBeaker; + IoCManager.InjectDependencies(this); + AutoModeButton.OnPressed += _ => OnToggleAuto?.Invoke(); + GrindButton.OnPressed += _ => OnGrind?.Invoke(); + JuiceButton.OnPressed += _ => OnJuice?.Invoke(); + ChamberContentBox.EjectButton.OnPressed += _ => OnEjectAll?.Invoke(); + BeakerContentBox.EjectButton.OnPressed += _ => OnEjectBeaker?.Invoke(); ChamberContentBox.BoxContents.OnItemSelected += OnChamberBoxContentsItemSelected; BeakerContentBox.BoxContents.SelectMode = ItemList.ItemListSelectMode.None; } private void OnChamberBoxContentsItemSelected(ItemList.ItemListSelectedEventArgs args) { - _owner.EjectChamberContent(_chamberVisualContents[args.ItemIndex]); - } - - protected override void Dispose(bool disposing) - { - base.Dispose(disposing); - - _chamberVisualContents.Clear(); - GrindButton.OnPressed -= _owner.StartGrinding; - JuiceButton.OnPressed -= _owner.StartJuicing; - ChamberContentBox.EjectButton.OnPressed -= _owner.EjectAll; - BeakerContentBox.EjectButton.OnPressed -= _owner.EjectBeaker; - ChamberContentBox.BoxContents.OnItemSelected -= OnChamberBoxContentsItemSelected; + OnEjectChamber?.Invoke(_chamberVisualContents[args.ItemIndex]); } public void UpdateState(ReagentGrinderInterfaceState state) diff --git a/Content.Client/Kitchen/UI/MicrowaveBoundUserInterface.cs b/Content.Client/Kitchen/UI/MicrowaveBoundUserInterface.cs index 7e7dd2d6935e..643ac47054bf 100644 --- a/Content.Client/Kitchen/UI/MicrowaveBoundUserInterface.cs +++ b/Content.Client/Kitchen/UI/MicrowaveBoundUserInterface.cs @@ -3,6 +3,7 @@ using JetBrains.Annotations; using Robust.Client.GameObjects; using Robust.Client.Graphics; +using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; using Robust.Shared.Timing; @@ -19,28 +20,15 @@ public sealed class MicrowaveBoundUserInterface : BoundUserInterface [ViewVariables] private readonly Dictionary _reagents = new(); - [Dependency] private readonly IGameTiming _gameTiming = default!; - - public MicrowaveUpdateUserInterfaceState currentState = default!; - - private IEntityManager _entManager; public MicrowaveBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey) { - _entManager = IoCManager.Resolve(); - } - - public TimeSpan GetCurrentTime() - { - return _gameTiming.CurTime; } protected override void Open() { base.Open(); - _menu = new MicrowaveMenu(this); - _menu.OpenCentered(); - _menu.OnClose += Close; + _menu = this.CreateWindow(); _menu.StartButton.OnPressed += _ => SendPredictedMessage(new MicrowaveStartCookMessage()); _menu.EjectButton.OnPressed += _ => SendPredictedMessage(new MicrowaveEjectMessage()); _menu.IngredientsList.OnItemSelected += args => @@ -74,38 +62,23 @@ protected override void Open() }; } - protected override void Dispose(bool disposing) - { - base.Dispose(disposing); - - if (!disposing) - { - return; - } - - _solids.Clear(); - _menu?.Dispose(); - } - protected override void UpdateState(BoundUserInterfaceState state) { base.UpdateState(state); - if (state is not MicrowaveUpdateUserInterfaceState cState) + if (state is not MicrowaveUpdateUserInterfaceState cState || _menu == null) { return; } + _menu.IsBusy = cState.IsMicrowaveBusy; + _menu.CurrentCooktimeEnd = cState.CurrentCookTimeEnd; - _menu?.ToggleBusyDisableOverlayPanel(cState.IsMicrowaveBusy || cState.ContainedSolids.Length == 0); - currentState = cState; - + _menu.ToggleBusyDisableOverlayPanel(cState.IsMicrowaveBusy || cState.ContainedSolids.Length == 0); // TODO move this to a component state and ensure the net ids. - RefreshContentsDisplay(_entManager.GetEntityArray(cState.ContainedSolids)); - - if (_menu == null) return; + RefreshContentsDisplay(EntMan.GetEntityArray(cState.ContainedSolids)); //Set the cook time info label - var cookTime = cState.ActiveButtonIndex == 0 + var cookTime = cState.ActiveButtonIndex == 0 ? Loc.GetString("microwave-menu-instant-button") : cState.CurrentCookTime.ToString(); diff --git a/Content.Client/Kitchen/UI/MicrowaveMenu.xaml.cs b/Content.Client/Kitchen/UI/MicrowaveMenu.xaml.cs index b292e9f1465c..13029e384694 100644 --- a/Content.Client/Kitchen/UI/MicrowaveMenu.xaml.cs +++ b/Content.Client/Kitchen/UI/MicrowaveMenu.xaml.cs @@ -9,22 +9,21 @@ namespace Content.Client.Kitchen.UI [GenerateTypedNameReferences] public sealed partial class MicrowaveMenu : FancyWindow { - public sealed class MicrowaveCookTimeButton : Button - { - public uint CookTime; - } + [Dependency] private readonly IGameTiming _timing = default!; public event Action? OnCookTimeSelected; public ButtonGroup CookTimeButtonGroup { get; } - private readonly MicrowaveBoundUserInterface _owner; - public MicrowaveMenu(MicrowaveBoundUserInterface owner) + public bool IsBusy; + public TimeSpan CurrentCooktimeEnd; + + public MicrowaveMenu() { RobustXamlLoader.Load(this); + IoCManager.InjectDependencies(this); CookTimeButtonGroup = new ButtonGroup(); InstantCookButton.Group = CookTimeButtonGroup; - _owner = owner; InstantCookButton.OnPressed += args => { OnCookTimeSelected?.Invoke(args, 0); @@ -65,14 +64,20 @@ public void ToggleBusyDisableOverlayPanel(bool shouldDisable) protected override void FrameUpdate(FrameEventArgs args) { base.FrameUpdate(args); - if(!_owner.currentState.IsMicrowaveBusy) + + if (!IsBusy) return; - if(_owner.currentState.CurrentCookTimeEnd > _owner.GetCurrentTime()) + if (CurrentCooktimeEnd > _timing.CurTime) { CookTimeInfoLabel.Text = Loc.GetString("microwave-bound-user-interface-cook-time-label", - ("time",_owner.currentState.CurrentCookTimeEnd.Subtract(_owner.GetCurrentTime()).Seconds)); + ("time", CurrentCooktimeEnd.Subtract(_timing.CurTime).Seconds)); } } + + public sealed class MicrowaveCookTimeButton : Button + { + public uint CookTime; + } } } diff --git a/Content.Client/Kitchen/UI/ReagentGrinderBoundUserInterface.cs b/Content.Client/Kitchen/UI/ReagentGrinderBoundUserInterface.cs index e6f108b3050e..bc4cc75b4d1b 100644 --- a/Content.Client/Kitchen/UI/ReagentGrinderBoundUserInterface.cs +++ b/Content.Client/Kitchen/UI/ReagentGrinderBoundUserInterface.cs @@ -1,6 +1,7 @@ using Content.Shared.Containers.ItemSlots; using Content.Shared.Kitchen; using Robust.Client.GameObjects; +using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; using Robust.Shared.Prototypes; @@ -8,8 +9,6 @@ namespace Content.Client.Kitchen.UI { public sealed class ReagentGrinderBoundUserInterface : BoundUserInterface { - [Dependency] private readonly IPrototypeManager _prototypeManager = default!; - [ViewVariables] private GrinderMenu? _menu; @@ -21,20 +20,13 @@ protected override void Open() { base.Open(); - _menu = new GrinderMenu(this, EntMan, _prototypeManager); - _menu.OpenCentered(); - _menu.OnClose += Close; - } - - protected override void Dispose(bool disposing) - { - base.Dispose(disposing); - if (!disposing) - { - return; - } - - _menu?.Dispose(); + _menu = this.CreateWindow(); + _menu.OnToggleAuto += ToggleAutoMode; + _menu.OnGrind += StartGrinding; + _menu.OnJuice += StartJuicing; + _menu.OnEjectAll += EjectAll; + _menu.OnEjectBeaker += EjectBeaker; + _menu.OnEjectChamber += EjectChamberContent; } protected override void UpdateState(BoundUserInterfaceState state) @@ -52,27 +44,27 @@ protected override void ReceiveMessage(BoundUserInterfaceMessage message) _menu?.HandleMessage(message); } - public void ToggleAutoMode(BaseButton.ButtonEventArgs args) + public void ToggleAutoMode() { SendMessage(new ReagentGrinderToggleAutoModeMessage()); } - public void StartGrinding(BaseButton.ButtonEventArgs? _ = null) + public void StartGrinding() { SendMessage(new ReagentGrinderStartMessage(GrinderProgram.Grind)); } - public void StartJuicing(BaseButton.ButtonEventArgs? _ = null) + public void StartJuicing() { SendMessage(new ReagentGrinderStartMessage(GrinderProgram.Juice)); } - public void EjectAll(BaseButton.ButtonEventArgs? _ = null) + public void EjectAll() { SendMessage(new ReagentGrinderEjectChamberAllMessage()); } - public void EjectBeaker(BaseButton.ButtonEventArgs? _ = null) + public void EjectBeaker() { SendMessage(new ItemSlotButtonPressedEvent(SharedReagentGrinder.BeakerSlotId)); } diff --git a/Content.Client/Labels/UI/HandLabelerBoundUserInterface.cs b/Content.Client/Labels/UI/HandLabelerBoundUserInterface.cs index 555f1ff09e69..6b6561234122 100644 --- a/Content.Client/Labels/UI/HandLabelerBoundUserInterface.cs +++ b/Content.Client/Labels/UI/HandLabelerBoundUserInterface.cs @@ -1,6 +1,7 @@ using Content.Shared.Labels; using Content.Shared.Labels.Components; using Robust.Client.GameObjects; +using Robust.Client.UserInterface; namespace Content.Client.Labels.UI { @@ -23,13 +24,8 @@ protected override void Open() { base.Open(); - _window = new HandLabelerWindow(); - if (State != null) - UpdateState(State); + _window = this.CreateWindow(); - _window.OpenCentered(); - - _window.OnClose += Close; _window.OnLabelChanged += OnLabelChanged; Reload(); } @@ -51,13 +47,5 @@ public void Reload() _window.SetCurrentLabel(component.AssignedLabel); } - - protected override void Dispose(bool disposing) - { - base.Dispose(disposing); - if (!disposing) return; - _window?.Dispose(); - } } - } diff --git a/Content.Client/Lathe/LatheSystem.cs b/Content.Client/Lathe/LatheSystem.cs index c72f01b39b14..386520c198fd 100644 --- a/Content.Client/Lathe/LatheSystem.cs +++ b/Content.Client/Lathe/LatheSystem.cs @@ -22,21 +22,29 @@ private void OnAppearanceChange(EntityUid uid, LatheComponent component, ref App if (args.Sprite == null) return; + // Lathe specific stuff + if (_appearance.TryGetData(uid, LatheVisuals.IsRunning, out var isRunning, args.Component)) + { + if (args.Sprite.LayerMapTryGet(LatheVisualLayers.IsRunning, out var runningLayer) && + component.RunningState != null && + component.IdleState != null) + { + var state = isRunning ? component.RunningState : component.IdleState; + args.Sprite.LayerSetState(runningLayer, state); + } + } + if (_appearance.TryGetData(uid, PowerDeviceVisuals.Powered, out var powered, args.Component) && args.Sprite.LayerMapTryGet(PowerDeviceVisualLayers.Powered, out var powerLayer)) { args.Sprite.LayerSetVisible(powerLayer, powered); - } - // Lathe specific stuff - if (_appearance.TryGetData(uid, LatheVisuals.IsRunning, out var isRunning, args.Component) && - args.Sprite.LayerMapTryGet(LatheVisualLayers.IsRunning, out var runningLayer) && - component.RunningState != null && - component.IdleState != null) - { - var state = isRunning ? component.RunningState : component.IdleState; - args.Sprite.LayerSetAnimationTime(runningLayer, 0f); - args.Sprite.LayerSetState(runningLayer, state); + if (component.UnlitIdleState != null && + component.UnlitRunningState != null) + { + var state = isRunning ? component.UnlitRunningState : component.UnlitIdleState; + args.Sprite.LayerSetState(powerLayer, state); + } } } diff --git a/Content.Client/Lathe/UI/LatheBoundUserInterface.cs b/Content.Client/Lathe/UI/LatheBoundUserInterface.cs index 6e6d1b917615..a599f79152e3 100644 --- a/Content.Client/Lathe/UI/LatheBoundUserInterface.cs +++ b/Content.Client/Lathe/UI/LatheBoundUserInterface.cs @@ -1,6 +1,7 @@ using Content.Shared.Lathe; using Content.Shared.Research.Components; using JetBrains.Annotations; +using Robust.Client.UserInterface; namespace Content.Client.Lathe.UI { @@ -17,9 +18,9 @@ protected override void Open() { base.Open(); - _menu = new LatheMenu(this); - _menu.OnClose += Close; - + _menu = this.CreateWindow(); + _menu.SetEntity(Owner); + _menu.OpenCenteredRight(); _menu.OnServerListButtonPressed += _ => { @@ -30,8 +31,6 @@ protected override void Open() { SendMessage(new LatheQueueRecipeMessage(recipe, amount)); }; - - _menu.OpenCenteredRight(); } protected override void UpdateState(BoundUserInterfaceState state) @@ -50,13 +49,5 @@ protected override void UpdateState(BoundUserInterfaceState state) break; } } - - protected override void Dispose(bool disposing) - { - base.Dispose(disposing); - if (!disposing) - return; - _menu?.Dispose(); - } } } diff --git a/Content.Client/Lathe/UI/LatheMenu.xaml b/Content.Client/Lathe/UI/LatheMenu.xaml index 6f484d8c7be8..5b21f0bae66d 100644 --- a/Content.Client/Lathe/UI/LatheMenu.xaml +++ b/Content.Client/Lathe/UI/LatheMenu.xaml @@ -100,12 +100,9 @@ Margin="5 0 0 0" Text="{Loc 'lathe-menu-fabricating-message'}"> - - + - - + + + + ? CurrentCategory; - public LatheMenu(LatheBoundUserInterface owner) + public EntityUid Entity; + + public LatheMenu() { - _owner = owner.Owner; RobustXamlLoader.Load(this); IoCManager.InjectDependencies(this); @@ -47,8 +44,6 @@ public LatheMenu(LatheBoundUserInterface owner) _lathe = _entityManager.System(); _materialStorage = _entityManager.System(); - Title = _entityManager.GetComponent(owner.Owner).EntityName; - SearchBar.OnTextChanged += _ => { PopulateRecipes(); @@ -61,8 +56,13 @@ public LatheMenu(LatheBoundUserInterface owner) FilterOption.OnItemSelected += OnItemSelected; ServerListButton.OnPressed += a => OnServerListButtonPressed?.Invoke(a); + } - if (_entityManager.TryGetComponent(owner.Owner, out var latheComponent)) + public void SetEntity(EntityUid uid) + { + Entity = uid; + + if (_entityManager.TryGetComponent(Entity, out var latheComponent)) { if (!latheComponent.DynamicRecipes.Any()) { @@ -70,7 +70,7 @@ public LatheMenu(LatheBoundUserInterface owner) } } - MaterialsList.SetOwner(owner.Owner); + MaterialsList.SetOwner(Entity); } /// @@ -78,9 +78,6 @@ public LatheMenu(LatheBoundUserInterface owner) /// public void PopulateRecipes() { - if (!_entityManager.TryGetComponent(_owner, out var component)) - return; - var recipesToShow = new List(); foreach (var recipe in Recipes) { @@ -92,7 +89,7 @@ public void PopulateRecipes() if (SearchBar.Text.Trim().Length != 0) { - if (proto.Name.ToLowerInvariant().Contains(SearchBar.Text.Trim().ToLowerInvariant())) + if (_lathe.GetRecipeName(recipe).ToLowerInvariant().Contains(SearchBar.Text.Trim().ToLowerInvariant())) recipesToShow.Add(proto); } else @@ -104,25 +101,15 @@ public void PopulateRecipes() if (!int.TryParse(AmountLineEdit.Text, out var quantity) || quantity <= 0) quantity = 1; - var sortedRecipesToShow = recipesToShow.OrderBy(p => p.Name); + var sortedRecipesToShow = recipesToShow.OrderBy(_lathe.GetRecipeName); RecipeList.Children.Clear(); + _entityManager.TryGetComponent(Entity, out LatheComponent? lathe); + foreach (var prototype in sortedRecipesToShow) { - List textures; - if (_prototypeManager.TryIndex(prototype.Result, out EntityPrototype? entityProto) && entityProto != null) - { - textures = SpriteComponent.GetPrototypeTextures(entityProto, _resources).Select(o => o.Default).ToList(); - } - else - { - textures = prototype.Icon == null - ? new List { _spriteSystem.GetPrototypeIcon(prototype.Result).Default } - : new List { _spriteSystem.Frame0(prototype.Icon) }; - } - - var canProduce = _lathe.CanProduce(_owner, prototype, quantity); + var canProduce = _lathe.CanProduce(Entity, prototype, quantity, component: lathe); - var control = new RecipeControl(prototype, () => GenerateTooltipText(prototype), canProduce, textures); + var control = new RecipeControl(_lathe, prototype, () => GenerateTooltipText(prototype), canProduce, GetRecipeDisplayControl(prototype)); control.OnButtonPressed += s => { if (!int.TryParse(AmountLineEdit.Text, out var amount) || amount <= 0) @@ -136,19 +123,20 @@ public void PopulateRecipes() private string GenerateTooltipText(LatheRecipePrototype prototype) { StringBuilder sb = new(); + var multiplier = _entityManager.GetComponent(Entity).MaterialUseMultiplier; - foreach (var (id, amount) in prototype.RequiredMaterials) + foreach (var (id, amount) in prototype.Materials) { - if (!_prototypeManager.TryIndex(id, out var proto)) + if (!_prototypeManager.TryIndex(id, out var proto)) continue; - var adjustedAmount = SharedLatheSystem.AdjustMaterial(amount, prototype.ApplyMaterialDiscount, _entityManager.GetComponent(_owner).MaterialUseMultiplier); + var adjustedAmount = SharedLatheSystem.AdjustMaterial(amount, prototype.ApplyMaterialDiscount, multiplier); var sheetVolume = _materialStorage.GetSheetVolume(proto); var unit = Loc.GetString(proto.Unit); var sheets = adjustedAmount / (float) sheetVolume; - var availableAmount = _materialStorage.GetMaterialAmount(_owner, id); + var availableAmount = _materialStorage.GetMaterialAmount(Entity, id); var missingAmount = Math.Max(0, adjustedAmount - availableAmount); var missingSheets = missingAmount / (float) sheetVolume; @@ -168,8 +156,9 @@ private string GenerateTooltipText(LatheRecipePrototype prototype) sb.AppendLine(tooltipText); } - if (!string.IsNullOrWhiteSpace(prototype.Description)) - sb.AppendLine(Loc.GetString("lathe-menu-description-display", ("description", prototype.Description))); + var desc = _lathe.GetRecipeDescription(prototype); + if (!string.IsNullOrWhiteSpace(desc)) + sb.AppendLine(Loc.GetString("lathe-menu-description-display", ("description", desc))); // Remove last newline if (sb.Length > 0) @@ -219,14 +208,20 @@ public void UpdateCategories() /// public void PopulateQueueList(List queue) { - QueueList.Clear(); + QueueList.DisposeAllChildren(); + var idx = 1; foreach (var recipe in queue) { - var icon = recipe.Icon == null - ? _spriteSystem.GetPrototypeIcon(recipe.Result).Default - : _spriteSystem.Frame0(recipe.Icon); - QueueList.AddItem($"{idx}. {recipe.Name}", icon); + var queuedRecipeBox = new BoxContainer(); + queuedRecipeBox.Orientation = BoxContainer.LayoutOrientation.Horizontal; + + queuedRecipeBox.AddChild(GetRecipeDisplayControl(recipe)); + + var queuedRecipeLabel = new Label(); + queuedRecipeLabel.Text = $"{idx}. {_lathe.GetRecipeName(recipe)}"; + queuedRecipeBox.AddChild(queuedRecipeLabel); + QueueList.AddChild(queuedRecipeBox); idx++; } } @@ -236,10 +231,30 @@ public void SetQueueInfo(LatheRecipePrototype? recipe) FabricatingContainer.Visible = recipe != null; if (recipe == null) return; - Icon.Texture = recipe.Icon == null - ? _spriteSystem.GetPrototypeIcon(recipe.Result).Default - : _spriteSystem.Frame0(recipe.Icon); - NameLabel.Text = $"{recipe.Name}"; + + FabricatingDisplayContainer.Children.Clear(); + FabricatingDisplayContainer.AddChild(GetRecipeDisplayControl(recipe)); + + NameLabel.Text = _lathe.GetRecipeName(recipe); + } + + public Control GetRecipeDisplayControl(LatheRecipePrototype recipe) + { + if (recipe.Icon != null) + { + var textRect = new TextureRect(); + textRect.Texture = _spriteSystem.Frame0(recipe.Icon); + return textRect; + } + + if (recipe.Result is { } result) + { + var entProtoView = new EntityPrototypeView(); + entProtoView.SetPrototype(result); + return entProtoView; + } + + return new Control(); } private void OnItemSelected(OptionButton.ItemSelectedEventArgs obj) diff --git a/Content.Client/Lathe/UI/RecipeControl.xaml b/Content.Client/Lathe/UI/RecipeControl.xaml index d1371a026a22..1105ab478ffc 100644 --- a/Content.Client/Lathe/UI/RecipeControl.xaml +++ b/Content.Client/Lathe/UI/RecipeControl.xaml @@ -5,14 +5,12 @@ Margin="0" StyleClasses="ButtonSquare"> - diff --git a/Content.Client/Lathe/UI/RecipeControl.xaml.cs b/Content.Client/Lathe/UI/RecipeControl.xaml.cs index 47b6b5932c47..4f438c8a8e54 100644 --- a/Content.Client/Lathe/UI/RecipeControl.xaml.cs +++ b/Content.Client/Lathe/UI/RecipeControl.xaml.cs @@ -1,8 +1,6 @@ using Content.Shared.Research.Prototypes; using Robust.Client.AutoGenerated; -using Robust.Client.Graphics; using Robust.Client.UserInterface; -using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.XAML; namespace Content.Client.Lathe.UI; @@ -13,12 +11,12 @@ public sealed partial class RecipeControl : Control public Action? OnButtonPressed; public Func TooltipTextSupplier; - public RecipeControl(LatheRecipePrototype recipe, Func tooltipTextSupplier, bool canProduce, List textures) + public RecipeControl(LatheSystem latheSystem, LatheRecipePrototype recipe, Func tooltipTextSupplier, bool canProduce, Control displayControl) { RobustXamlLoader.Load(this); - RecipeName.Text = recipe.Name; - RecipeTextures.Textures = textures; + RecipeName.Text = latheSystem.GetRecipeName(recipe); + RecipeDisplayContainer.AddChild(displayControl); Button.Disabled = !canProduce; TooltipTextSupplier = tooltipTextSupplier; Button.TooltipSupplier = SupplyTooltip; diff --git a/Content.Client/Launcher/LauncherConnectingGui.xaml.cs b/Content.Client/Launcher/LauncherConnectingGui.xaml.cs index ac74ad7b60d2..5015b710eb48 100644 --- a/Content.Client/Launcher/LauncherConnectingGui.xaml.cs +++ b/Content.Client/Launcher/LauncherConnectingGui.xaml.cs @@ -116,7 +116,7 @@ private void HandleDisconnectReason(INetStructuredReason? reason) private void ChangeLoginTip() { var tipsDataset = _cfg.GetCVar(CCVars.LoginTipsDataset); - var loginTipsEnabled = _prototype.TryIndex(tipsDataset, out var tips); + var loginTipsEnabled = _prototype.TryIndex(tipsDataset, out var tips); LoginTips.Visible = loginTipsEnabled; if (!loginTipsEnabled) @@ -131,7 +131,7 @@ private void ChangeLoginTip() var randomIndex = _random.Next(tipList.Count); var tip = tipList[randomIndex]; - LoginTip.SetMessage(tip); + LoginTip.SetMessage(Loc.GetString(tip)); LoginTipTitle.Text = Loc.GetString("connecting-window-tip", ("numberTip", randomIndex)); } diff --git a/Content.Client/Light/EntitySystems/LightBehaviorSystem.cs b/Content.Client/Light/EntitySystems/LightBehaviorSystem.cs index 11f69165cf65..ca19d8522c56 100644 --- a/Content.Client/Light/EntitySystems/LightBehaviorSystem.cs +++ b/Content.Client/Light/EntitySystems/LightBehaviorSystem.cs @@ -19,6 +19,9 @@ public override void Initialize() private void OnBehaviorAnimationCompleted(EntityUid uid, LightBehaviourComponent component, AnimationCompletedEvent args) { + if (!args.Finished) + return; + var container = component.Animations.FirstOrDefault(x => x.FullKey == args.Key); if (container == null) diff --git a/Content.Client/Light/EntitySystems/RotatingLightSystem.cs b/Content.Client/Light/EntitySystems/RotatingLightSystem.cs index 842c13dedfe9..5c2c4e4c875b 100644 --- a/Content.Client/Light/EntitySystems/RotatingLightSystem.cs +++ b/Content.Client/Light/EntitySystems/RotatingLightSystem.cs @@ -69,6 +69,9 @@ private void OnAfterAutoHandleState(EntityUid uid, RotatingLightComponent comp, private void OnAnimationComplete(EntityUid uid, RotatingLightComponent comp, AnimationCompletedEvent args) { + if (!args.Finished) + return; + PlayAnimation(uid, comp); } diff --git a/Content.Client/Lobby/LobbyUIController.cs b/Content.Client/Lobby/LobbyUIController.cs index e4a13ed8c6b7..1cdaaccc4e8d 100644 --- a/Content.Client/Lobby/LobbyUIController.cs +++ b/Content.Client/Lobby/LobbyUIController.cs @@ -46,6 +46,7 @@ public sealed class LobbyUIController : UIController, IOnStateEntered /// This is the characher preview panel in the chat. This should only update if their character updates. @@ -214,6 +215,46 @@ private void SaveProfile() ReloadCharacterSetup(); } + private void CloseProfileEditor() + { + if (_profileEditor == null) + return; + + _profileEditor.SetProfile(null, null); + _profileEditor.Visible = false; + + if (_stateManager.CurrentState is LobbyState lobbyGui) + { + lobbyGui.SwitchState(LobbyGui.LobbyGuiState.Default); + } + } + + private void OpenSavePanel() + { + if (_savePanel is { IsOpen: true }) + return; + + _savePanel = new CharacterSetupGuiSavePanel(); + + _savePanel.SaveButton.OnPressed += _ => + { + SaveProfile(); + + _savePanel.Close(); + + CloseProfileEditor(); + }; + + _savePanel.NoSaveButton.OnPressed += _ => + { + _savePanel.Close(); + + CloseProfileEditor(); + }; + + _savePanel.OpenCentered(); + } + private (CharacterSetupGui, HumanoidProfileEditor) EnsureGui() { if (_characterSetup != null && _profileEditor != null) @@ -231,6 +272,7 @@ private void SaveProfile() _logManager, _playerManager, _prototypeManager, + _resourceCache, _requirements, _markings); @@ -240,14 +282,16 @@ private void SaveProfile() _characterSetup.CloseButton.OnPressed += _ => { - // Reset sliders etc. - _profileEditor.SetProfile(null, null); - _profileEditor.Visible = false; - - if (_stateManager.CurrentState is LobbyState lobbyGui) + // Open the save panel if we have unsaved changes. + if (_profileEditor.Profile != null && _profileEditor.IsDirty) { - lobbyGui.SwitchState(LobbyGui.LobbyGuiState.Default); + OpenSavePanel(); + + return; } + + // Reset sliders etc. + CloseProfileEditor(); }; _profileEditor.Save += SaveProfile; diff --git a/Content.Client/Lobby/UI/CharacterSetupGuiSavePanel.xaml b/Content.Client/Lobby/UI/CharacterSetupGuiSavePanel.xaml new file mode 100644 index 000000000000..2dcf9143533f --- /dev/null +++ b/Content.Client/Lobby/UI/CharacterSetupGuiSavePanel.xaml @@ -0,0 +1,10 @@ + + + +