diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 0bfc6fe3a7cf..38222148dbe3 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -7,3 +7,5 @@ /Resources/Maps/ @ss14Starlight/maintainer @ss14Starlight/mappers /Resources/Prototypes/ @ss14Starlight/maintainer @ss14Starlight/prototypers /Resources/ServerInfo/ @ss14Starlight/maintainer @ss14Starlight/wiki + +/Resources/Prototypes/_NullLink/ @StarlightHost diff --git a/Content.Client/Info/PlaytimeStats/PlaytimeStatsWindow.cs b/Content.Client/Info/PlaytimeStats/PlaytimeStatsWindow.cs index 2bb5f6207ec9..feded209dc69 100644 --- a/Content.Client/Info/PlaytimeStats/PlaytimeStatsWindow.cs +++ b/Content.Client/Info/PlaytimeStats/PlaytimeStatsWindow.cs @@ -18,6 +18,8 @@ public sealed partial class PlaytimeStatsWindow : FancyWindow private ISawmill _sawmill = Logger.GetSawmill("PlaytimeStatsWindow"); private readonly Color _altColor = Color.FromHex("#292B38"); private readonly Color _defaultColor = Color.FromHex("#2F2F3B"); + private readonly Color _antagColor = Color.FromHex("#fe7676"); + private readonly Color _ghostColor = Color.FromHex("#c996e0"); private bool _useAltColor; public PlaytimeStatsWindow() @@ -109,11 +111,12 @@ private void PopulatePlaytimeData() OverallPlaytimeLabel.Text = Loc.GetString("ui-playtime-overall", ("time", overallPlaytime)); - var rolePlaytimes = _jobRequirementsManager.FetchPlaytimeByRoles(); - - //starlight + // Starlight BEGIN + var rolePlaytimes = _jobRequirementsManager.FetchPlaytimeByRoles().ToList(); var departmentPlaytimes = _jobRequirementsManager.FetchPlaytimeByDepartments(); - //starlight end + var antagPlaytimes = _jobRequirementsManager.FetchPlaytimeByAntags(); + var miscellaneousPlaytimes = _jobRequirementsManager.FetchPlaytimeMiscellaneous(rolePlaytimes, antagPlaytimes); + // Starlight END RolesPlaytimeList.RemoveAllChildren(); PopulatePlaytimeHeader(); @@ -132,6 +135,16 @@ private void PopulatePlaytimeData() var playtime = departmentPlaytime.Value; AddRolePlaytimeEntryToTable(Loc.GetString(department.Name), playtime.ToString(), textColor: department.Color); //starlight edit } + foreach (var antagPlaytime in antagPlaytimes) + { + AddRolePlaytimeEntryToTable(Loc.GetString(antagPlaytime.Key.Name), antagPlaytime.Value.ToString(), textColor: _antagColor); + } + foreach (var miscellaneousPlaytime in miscellaneousPlaytimes) + { + var role = miscellaneousPlaytime.Key; + var playtime = miscellaneousPlaytime.Value; + AddRolePlaytimeEntryToTable(Loc.GetString(role.Name), playtime.ToString(), textColor: _ghostColor); + } //starlight end } diff --git a/Content.Client/Players/PlayTimeTracking/JobRequirementsManager.cs b/Content.Client/Players/PlayTimeTracking/JobRequirementsManager.cs index b915eb2d38bc..64feb4c48488 100644 --- a/Content.Client/Players/PlayTimeTracking/JobRequirementsManager.cs +++ b/Content.Client/Players/PlayTimeTracking/JobRequirementsManager.cs @@ -1,4 +1,5 @@ using System.Diagnostics.CodeAnalysis; +using System.Linq; using Content.Shared.CCVar; using Content.Shared.Players; using Content.Shared.Players.JobWhitelist; @@ -375,6 +376,50 @@ public IEnumerable> FetchPlaytimeByD yield return new KeyValuePair(department, departmentTime); } } + + /// + /// Fetches playtime per antag prototype. + /// b + public IEnumerable> FetchPlaytimeByAntags() + { + var antagsToMap = _prototypes.EnumeratePrototypes(); + foreach (var antag in antagsToMap) + { + if (antag.PlayTimeTracker == null) + continue; + + if (_mergedRoles.TryGetValue(antag.PlayTimeTracker, out var time)) + yield return new KeyValuePair(antag, time); + } + } + + /// + /// Fetches playtime for all PlayTimeTracker prototypes that we don't see in any job or antag. + /// This covers ghost roles and various admin spawns. + /// + public IEnumerable> FetchPlaytimeMiscellaneous( + IEnumerable> jobPlaytimes, + IEnumerable> antagPlaytimes) + { + var trackers = _prototypes.EnumeratePrototypes(); + var exclude = new HashSet { "Overall" }; + foreach (var jobPlaytime in jobPlaytimes) + exclude.Add(jobPlaytime.Key.PlayTimeTracker); + foreach (var antagPlaytime in antagPlaytimes) + if (antagPlaytime.Key.PlayTimeTracker != null) + exclude.Add(antagPlaytime.Key.PlayTimeTracker); + + foreach (var tracker in trackers) + { + if (exclude.Contains(tracker.ID)) + continue; + + if (!_mergedRoles.TryGetValue(tracker.ID, out var rolePlaytime)) + continue; + + yield return new KeyValuePair(tracker, rolePlaytime); + } + } //starlight end public IReadOnlyDictionary GetPlayTimes(ICommonSession session) diff --git a/Content.Client/Silicons/StationAi/StationAiOverlay.cs b/Content.Client/Silicons/StationAi/StationAiOverlay.cs index 0fe3f2c830ec..2c0b2bf86045 100644 --- a/Content.Client/Silicons/StationAi/StationAiOverlay.cs +++ b/Content.Client/Silicons/StationAi/StationAiOverlay.cs @@ -36,9 +36,17 @@ public sealed class StationAiOverlay : Overlay private readonly NavMapControl _navMap = new(); // Carpmosia-edit - AI Navmap private readonly OverlayResourceCache _resources = new(); - private Dictionary _sRGBLookUp = new(); // Carpmosia-edit - AI Navmap - private float _updateRate = 1f / 30f; + // Carpmosia-start - AI Navmap + private readonly Dictionary _sRgbLookUp = new(); + private static readonly RenderTargetFormatParameters RenderTargetFormatParameters = new(RenderTargetColorFormat.Rgba8Srgb); + + private static readonly List TileLinesToDraw = []; + private static readonly List TileRectsToDraw = []; + + private const float UpdateRate = 1f / 30f; + // Carpmosia-end - AI Navmap + private float _accumulator; public StationAiOverlay() @@ -59,30 +67,32 @@ protected override void Draw(in OverlayDrawArgs args) { res.StaticTexture?.Dispose(); res.StencilTexture?.Dispose(); - res.StencilTexture = _clyde.CreateRenderTarget(args.Viewport.Size, new RenderTargetFormatParameters(RenderTargetColorFormat.Rgba8Srgb), name: "station-ai-stencil"); + + // Carpmosia-start - AI Navmap + res.StencilTexture = _clyde.CreateRenderTarget(args.Viewport.Size, RenderTargetFormatParameters, name: "station-ai-stencil"); res.StaticTexture = _clyde.CreateRenderTarget(args.Viewport.Size, - new RenderTargetFormatParameters(RenderTargetColorFormat.Rgba8Srgb), + RenderTargetFormatParameters, name: "station-ai-static"); + // Carpmosia-end - AI Navmap } var worldHandle = args.WorldHandle; var worldBounds = args.WorldBounds; - // var playerEnt = _player.LocalEntity; - // Starlight-start: moved to be after new playerEnt definition with edit - var playerEnt = _player.LocalEntity; + // Starlight-start: moved to be after new playerEnt definition with edit + var playerEnt = _player.LocalEntity; // Check for cross-grid viewing (e.g., Abductor remote eye) BEFORE getting gridUid - if (_entManager.TryGetComponent(playerEnt, out StationAiOverlayComponent? stationAiOverlay) - && stationAiOverlay.AllowCrossGrid + if (_entManager.TryGetComponent(playerEnt, out StationAiOverlayComponent? stationAiOverlay) + && stationAiOverlay.AllowCrossGrid && _entManager.TryGetComponent(playerEnt, out RelayInputMoverComponent? relay)) playerEnt = relay.RelayEntity; // Starlight - start _entManager.TryGetComponent(playerEnt, out StationAiOverlayComponent? relayStationAiOverlay); // Starlight - end - + _entManager.TryGetComponent(playerEnt, out TransformComponent? playerXform); var gridUid = playerXform?.GridUid ?? EntityUid.Invalid; _entManager.TryGetComponent(gridUid, out MapGridComponent? grid); @@ -101,10 +111,10 @@ protected override void Draw(in OverlayDrawArgs args) if (stationAiOverlay is not null) // 🌟Starlight🌟 color = color.WithAlpha(stationAiOverlay.Alfa); // 🌟Starlight🌟 - _navMap.AiFrameUpdate((float) _timing.FrameTime.TotalSeconds, gridUid); // Carpmosia-edit - AI Navmap + _navMap.AiFrameUpdate((float)_timing.FrameTime.TotalSeconds, gridUid); // Carpmosia-edit - AI Navmap if (_accumulator <= 0f) { - _accumulator = MathF.Max(0f, _accumulator + _updateRate); + _accumulator = MathF.Max(0f, _accumulator + UpdateRate); // Carpmosia-edit - AI Navmap _visibleTiles.Clear(); // Starlight - start _visibleTileTags.Clear(); @@ -212,65 +222,67 @@ public void Dispose() // Carpmosia-start - AI Navmap protected void DrawNavMap(DrawingHandleWorld handle, MapGridComponent grid) { - if (!_sRGBLookUp.TryGetValue(_navMap.WallColor, out var wallsRGB)) + if (!_sRgbLookUp.TryGetValue(_navMap.WallColor, out var wallsRgb)) { - wallsRGB = Color.ToSrgb(_navMap.WallColor); - _sRGBLookUp[_navMap.WallColor] = wallsRGB; + wallsRgb = Color.ToSrgb(_navMap.WallColor); + _sRgbLookUp[_navMap.WallColor] = wallsRgb; } // Draw floor tiles - if (_navMap.TilePolygons.Any()) + if (_navMap.TilePolygons.Count != 0) { foreach (var (polygonVerts, polygonColor) in _navMap.TilePolygons) { - handle.DrawPrimitives(DrawPrimitiveTopology.TriangleFan, polygonVerts[..polygonVerts.Length], polygonColor); + handle.DrawPrimitives(DrawPrimitiveTopology.TriangleFan, polygonVerts.AsSpan()[..], polygonColor); } } // Draw map lines - if (_navMap.TileLines.Any()) + if (_navMap.TileLines.Count != 0) { - var lines = new ValueList(_navMap.TileLines.Count * 2); + TileLinesToDraw.Clear(); + TileLinesToDraw.EnsureCapacity(_navMap.TileLines.Count * 2); foreach (var (o, t) in _navMap.TileLines) { - var origin = new Vector2(o.X, -o.Y); - var terminus = new Vector2(t.X, -t.Y); + var origin = o with { Y = -o.Y }; + var terminus = t with { Y = -t.Y }; - lines.Add(origin); - lines.Add(terminus); + TileLinesToDraw.Add(origin); + TileLinesToDraw.Add(terminus); } - if (lines.Count > 0) - handle.DrawPrimitives(DrawPrimitiveTopology.LineList, lines.Span, wallsRGB); + if (TileLinesToDraw.Count > 0) + handle.DrawPrimitives(DrawPrimitiveTopology.LineList, TileLinesToDraw, wallsRgb); } // Draw map rects - if (_navMap.TileRects.Any()) + if (_navMap.TileRects.Count != 0) { - var rects = new ValueList(_navMap.TileRects.Count * 8); + TileRectsToDraw.Clear(); + TileRectsToDraw.EnsureCapacity(_navMap.TileRects.Count * 8); foreach (var (lt, rb) in _navMap.TileRects) { - var leftTop = new Vector2(lt.X, -lt.Y); - var rightBottom = new Vector2(rb.X, -rb.Y); + var leftTop = lt with { Y = -lt.Y }; + var rightBottom = rb with { Y = -rb.Y }; var rightTop = new Vector2(rightBottom.X, leftTop.Y); var leftBottom = new Vector2(leftTop.X, rightBottom.Y); - rects.Add(leftTop); - rects.Add(rightTop); - rects.Add(rightTop); - rects.Add(rightBottom); - rects.Add(rightBottom); - rects.Add(leftBottom); - rects.Add(leftBottom); - rects.Add(leftTop); + TileRectsToDraw.Add(leftTop); + TileRectsToDraw.Add(rightTop); + TileRectsToDraw.Add(rightTop); + TileRectsToDraw.Add(rightBottom); + TileRectsToDraw.Add(rightBottom); + TileRectsToDraw.Add(leftBottom); + TileRectsToDraw.Add(leftBottom); + TileRectsToDraw.Add(leftTop); } - if (rects.Count > 0) - handle.DrawPrimitives(DrawPrimitiveTopology.LineList, rects.Span, wallsRGB); + if (TileRectsToDraw.Count > 0) + handle.DrawPrimitives(DrawPrimitiveTopology.LineList, TileRectsToDraw, wallsRgb); } } // Carpmosia-end - AI Navmap -} +} \ No newline at end of file diff --git a/Content.Client/Store/Ui/StoreListingControl.xaml.cs b/Content.Client/Store/Ui/StoreListingControl.xaml.cs index c7eafe2cac13..083ff6f49ebb 100644 --- a/Content.Client/Store/Ui/StoreListingControl.xaml.cs +++ b/Content.Client/Store/Ui/StoreListingControl.xaml.cs @@ -103,7 +103,7 @@ private void UpdateBuyButtonText() var m = _priceNumberRegex.Match(_price); if (m.Success) { - StoreItemBuyButton.Text = $"{m.Groups[1].Value}�"; + StoreItemBuyButton.Text = $"{m.Groups[1].Value}¢"; } else { diff --git a/Content.Client/_NullLink/UI/Hub.cs b/Content.Client/_NullLink/UI/Hub.cs index ca1df585b132..ee7303fdf5a2 100644 --- a/Content.Client/_NullLink/UI/Hub.cs +++ b/Content.Client/_NullLink/UI/Hub.cs @@ -23,8 +23,8 @@ namespace Content.Client._NullLink.UI; -// It�s not finished, still needs a lot of info displayed, scroll support once more servers show up, max hub width, a hide button, etc. -// But I�m rushing it for the upstream, will finish it properly someday. +// It’s not finished, still needs a lot of info displayed, scroll support once more servers show up, max hub width, a hide button, etc. +// But I’m rushing it for the upstream, will finish it properly someday. internal sealed class Hub : PanelContainer, IDisposable { [Dependency] private readonly ILogManager _logs = default!; @@ -59,8 +59,8 @@ public Hub() }; AddChild(_gridContainer); - // This crap throws a NullRef exception�what the hell, the Try method doesn�t even check for null, - // and Init is private, so there�s no way to figure out what�s going on in there. + // This crap throws a NullRef exception—what the hell, the Try method doesn’t even check for null, + // and Init is private, so there’s no way to figure out what’s going on in there. //try //{ // if (_systemManager.TryGetEntitySystem(out var hub)) diff --git a/Content.Client/_Starlight/Commands/OpenLogLevelsCommand.cs b/Content.Client/_Starlight/Commands/OpenLogLevelsCommand.cs new file mode 100644 index 000000000000..f6dcf8f37c68 --- /dev/null +++ b/Content.Client/_Starlight/Commands/OpenLogLevelsCommand.cs @@ -0,0 +1,18 @@ +using Content.Client._Starlight.Logs; +using Robust.Client.UserInterface; +using Robust.Shared.Console; + +namespace Content.Client._Starlight.Commands; + +public sealed class OpenLogLevelsCommand : IConsoleCommand +{ + public string Command => "logs"; + public string Description => "Open the sawmill log level configuration window."; + public string Help => "logs"; + + public void Execute(IConsoleShell shell, string argStr, string[] args) + { + var window = new LogLevelsWindow(); + window.OpenCentered(); + } +} diff --git a/Content.Client/_Starlight/Logs/LogLevelSystem.cs b/Content.Client/_Starlight/Logs/LogLevelSystem.cs new file mode 100644 index 000000000000..456aaf003624 --- /dev/null +++ b/Content.Client/_Starlight/Logs/LogLevelSystem.cs @@ -0,0 +1,43 @@ +using Content.Shared.Starlight.CCVar; +using Robust.Shared.Configuration; +using Robust.Shared.Log; + +namespace Content.Client._Starlight.Logs; + +/// +/// Restores persisted sawmill log levels from CVar on startup. +/// +public sealed class LogLevelSystem : EntitySystem +{ + [Dependency] private readonly ILogManager _logManager = default!; + [Dependency] private readonly IConfigurationManager _cfg = default!; + + public override void Initialize() + { + base.Initialize(); + ApplySavedLevels(); + } + + private void ApplySavedLevels() + { + var raw = _cfg.GetCVar(StarlightCCVars.LogSawmillLevels); + if (string.IsNullOrEmpty(raw)) + return; + + foreach (var entry in raw.Split(';', StringSplitOptions.RemoveEmptyEntries)) + { + var sep = entry.IndexOf('='); + if (sep <= 0) + continue; + + var name = entry[..sep]; + var levelStr = entry[(sep + 1)..]; + + if (!Enum.TryParse(levelStr, out var level)) + continue; + + var sawmill = _logManager.GetSawmill(name); + sawmill.Level = level; + } + } +} diff --git a/Content.Client/_Starlight/Logs/LogLevelsWindow.cs b/Content.Client/_Starlight/Logs/LogLevelsWindow.cs new file mode 100644 index 000000000000..d8e65c4acb5f --- /dev/null +++ b/Content.Client/_Starlight/Logs/LogLevelsWindow.cs @@ -0,0 +1,123 @@ +using System.Linq; +using System.Text; +using Content.Shared.Starlight.CCVar; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.CustomControls; +using Robust.Shared.Configuration; +using Robust.Shared.Log; + +namespace Content.Client._Starlight.Logs; + +public sealed class LogLevelsWindow : DefaultWindow +{ + [Dependency] private readonly ILogManager _logManager = default!; + [Dependency] private readonly IConfigurationManager _cfg = default!; + + private static readonly string[] LevelNames = ["(inherit)", "Verbose", "Debug", "Info", "Warning", "Error", "Fatal"]; + private static readonly LogLevel?[] LevelValues = [null, LogLevel.Verbose, LogLevel.Debug, LogLevel.Info, LogLevel.Warning, LogLevel.Error, LogLevel.Fatal]; + + private readonly LineEdit _searchBox; + private readonly BoxContainer _sawmillList; + + public LogLevelsWindow() + { + IoCManager.InjectDependencies(this); + + Title = "Sawmill Log Levels"; + MinSize = new(450, 500); + SetSize = new(450, 600); + + var root = new BoxContainer + { + Orientation = BoxContainer.LayoutOrientation.Vertical, + HorizontalExpand = true, + VerticalExpand = true, + }; + + _searchBox = new LineEdit + { + PlaceHolder = "Search sawmill...", + HorizontalExpand = true, + Margin = new(4, 4, 4, 2), + }; + _searchBox.OnTextChanged += _ => Rebuild(); + root.AddChild(_searchBox); + + _sawmillList = new BoxContainer + { + Orientation = BoxContainer.LayoutOrientation.Vertical, + HorizontalExpand = true, + }; + + var scroll = new ScrollContainer + { + VerticalExpand = true, + HorizontalExpand = true, + Margin = new(4, 2, 4, 4), + }; + scroll.AddChild(_sawmillList); + root.AddChild(scroll); + + Contents.AddChild(root); + Rebuild(); + } + + private void Rebuild() + { + _sawmillList.RemoveAllChildren(); + + var filter = _searchBox.Text.Trim(); + var sawmills = _logManager.AllSawmills + .OrderBy(s => s.Name) + .Where(s => string.IsNullOrEmpty(filter) || s.Name.Contains(filter, StringComparison.OrdinalIgnoreCase)); + + foreach (var sawmill in sawmills) + { + var row = new BoxContainer + { + Orientation = BoxContainer.LayoutOrientation.Horizontal, + HorizontalExpand = true, + Margin = new(2, 1), + }; + + var label = new Label + { + Text = sawmill.Name, + HorizontalExpand = true, + ClipText = true, + }; + + var combo = new OptionButton { MinWidth = 100 }; + for (var i = 0; i < LevelNames.Length; i++) + combo.AddItem(LevelNames[i], i); + + var currentIdx = Array.IndexOf(LevelValues, sawmill.Level); + combo.SelectId(currentIdx >= 0 ? currentIdx : 0); + + var captured = sawmill; + combo.OnItemSelected += args => + { + combo.SelectId(args.Id); + captured.Level = LevelValues[args.Id]; + SaveLevels(); + }; + + row.AddChild(label); + row.AddChild(combo); + _sawmillList.AddChild(row); + } + } + + private void SaveLevels() + { + var sb = new StringBuilder(); + foreach (var sawmill in _logManager.AllSawmills) + { + if (sawmill.Level is { } level) + sb.Append(sawmill.Name).Append('=').Append(level).Append(';'); + } + + _cfg.SetCVar(StarlightCCVars.LogSawmillLevels, sb.ToString()); + _cfg.SaveToFile(); + } +} diff --git a/Content.Client/_Starlight/Plumbing/UI/ClickableBeakerBarChart.cs b/Content.Client/_Starlight/Plumbing/UI/ClickableBeakerBarChart.cs new file mode 100644 index 000000000000..d7610b3868a3 --- /dev/null +++ b/Content.Client/_Starlight/Plumbing/UI/ClickableBeakerBarChart.cs @@ -0,0 +1,109 @@ +using Content.Client.Medical.Cryogenics; +using Content.Client.Stylesheets.Colorspace; +using Content.Client.Stylesheets.Palette; +using Robust.Client.Graphics; +using Robust.Client.UserInterface.Controls; + +namespace Content.Client._Starlight.Plumbing.UI; + +public sealed class ClickableBeakerBarChart : ContainerButton +{ + private const float StateLightnessShift = 0.10f; + + private static readonly ColorPalette ButtonPalette = Palettes.Navy; + private static readonly Color IdleBackgroundColor = ButtonPalette.Element; + private static readonly Color ChartBackgroundColor = new(0.1f, 0.1f, 0.1f); + private static readonly Color HoverBackgroundColor = ButtonPalette.HoveredElement.NudgeLightness(StateLightnessShift); + private static readonly Color PressedBackgroundColor = ButtonPalette.PressedElement.NudgeLightness(StateLightnessShift); + + private readonly BeakerBarChart _chart; + + public event Action? OnChartPressed; + + public string ReagentId { get; set; } = string.Empty; + + public float Capacity + { + get => _chart.Capacity; + set => _chart.Capacity = value; + } + + public ClickableBeakerBarChart() + { + HorizontalExpand = true; + MouseFilter = MouseFilterMode.Stop; + ToolTip = string.Empty; + OnPressed += _ => HandlePressed(); + + var chartContainer = new BoxContainer + { + HorizontalExpand = true, + VerticalExpand = true, + Margin = new Thickness(4), + }; + + _chart = new BeakerBarChart + { + HorizontalExpand = true, + VerticalExpand = true, + MouseFilter = MouseFilterMode.Ignore, + BackgroundColor = ChartBackgroundColor, + }; + + chartContainer.AddChild(_chart); + AddChild(chartContainer); + UpdateButtonStyle(); + } + + public void Clear() + { + _chart.Clear(); + } + + public void SetEntry( + string uid, + string label, + float amount, + Color color, + Color? textColor = null, + string? tooltip = null) + { + ToolTip = tooltip; + _chart.SetEntry(uid, label, amount, color, textColor, tooltip); + } + + protected override void DrawModeChanged() + { + base.DrawModeChanged(); + UpdateButtonStyle(); + } + + private void HandlePressed() + { + if (string.IsNullOrEmpty(ReagentId)) + return; + + OnChartPressed?.Invoke(ReagentId); + } + + private void UpdateButtonStyle() + { + var backgroundColor = DrawMode switch + { + DrawModeEnum.Pressed => PressedBackgroundColor, + DrawModeEnum.Hover => HoverBackgroundColor, + _ => IdleBackgroundColor, + }; + + StyleBoxOverride = new StyleBoxFlat + { + BackgroundColor = backgroundColor, + BorderColor = Color.Transparent, + BorderThickness = new Thickness(0), + ContentMarginLeftOverride = 0, + ContentMarginTopOverride = 0, + ContentMarginRightOverride = 0, + ContentMarginBottomOverride = 0, + }; + } +} \ No newline at end of file diff --git a/Content.Client/_Starlight/Plumbing/UI/PlumbingSmartDispenserBoundUserInterface.cs b/Content.Client/_Starlight/Plumbing/UI/PlumbingSmartDispenserBoundUserInterface.cs index 0b4ab716e6ba..4488f4788534 100644 --- a/Content.Client/_Starlight/Plumbing/UI/PlumbingSmartDispenserBoundUserInterface.cs +++ b/Content.Client/_Starlight/Plumbing/UI/PlumbingSmartDispenserBoundUserInterface.cs @@ -1,4 +1,5 @@ using Content.Shared._Starlight.Plumbing; +using Content.Shared.Chemistry; using JetBrains.Annotations; using Robust.Client.UserInterface; @@ -17,6 +18,11 @@ protected override void Open() { base.Open(); _window = this.CreateWindow(); + + _window.AmountGrid.OnButtonPressed += value => SendMessage(new PlumbingSmartDispenserSetDispenseAmountMessage(value)); + _window.ClearButton.OnPressed += _ => SendMessage(new ReagentDispenserClearContainerSolutionMessage()); + _window.OnDispenseReagentPressed += reagentId => SendMessage(new PlumbingSmartDispenserDispenseReagentMessage(reagentId)); + SendMessage(new PlumbingSmartDispenserRequestActorStateMessage()); } protected override void UpdateState(BoundUserInterfaceState state) @@ -26,6 +32,14 @@ protected override void UpdateState(BoundUserInterfaceState state) if (_window == null || state is not PlumbingSmartDispenserBuiState cast) return; - _window.UpdateState(cast); + _window.UpdateSharedState(cast); + } + + protected override void ReceiveMessage(BoundUserInterfaceMessage message) + { + base.ReceiveMessage(message); + + if (message is PlumbingSmartDispenserActorStateMessage actorState) + _window?.UpdateActorState(actorState); } } diff --git a/Content.Client/_Starlight/Plumbing/UI/PlumbingSmartDispenserWindow.xaml b/Content.Client/_Starlight/Plumbing/UI/PlumbingSmartDispenserWindow.xaml index ee8d5b625a68..48f414778b3b 100644 --- a/Content.Client/_Starlight/Plumbing/UI/PlumbingSmartDispenserWindow.xaml +++ b/Content.Client/_Starlight/Plumbing/UI/PlumbingSmartDispenserWindow.xaml @@ -1,23 +1,55 @@ - -