diff --git a/.editorconfig b/.editorconfig index a87e5e0651..fa740a7511 100644 --- a/.editorconfig +++ b/.editorconfig @@ -351,7 +351,7 @@ resharper_csharp_qualified_using_at_nested_scope = false resharper_csharp_prefer_qualified_reference = false resharper_csharp_allow_alias = false -[*.{csproj,xml,yml,yaml,dll.config,msbuildproj,targets,props}] +[*.{csproj,xml,yml,yaml,dll.config,msbuildproj,targets,props,slnx}] indent_size = 2 [nuget.config] diff --git a/.github/workflows/build-docfx.yml b/.github/workflows/build-docfx.yml index 1f010b7291..dee31e9b31 100644 --- a/.github/workflows/build-docfx.yml +++ b/.github/workflows/build-docfx.yml @@ -21,7 +21,7 @@ jobs: - name: Setup .NET Core uses: actions/setup-dotnet@v4.1.0 with: - dotnet-version: 9.0.x + dotnet-version: 10.0.x - name: Install dependencies run: dotnet restore diff --git a/.github/workflows/build-map-renderer.yml b/.github/workflows/build-map-renderer.yml index f93f4b25ae..fb6be1603c 100644 --- a/.github/workflows/build-map-renderer.yml +++ b/.github/workflows/build-map-renderer.yml @@ -36,7 +36,7 @@ jobs: - name: Setup .NET Core uses: actions/setup-dotnet@v4.1.0 with: - dotnet-version: 9.0.x + dotnet-version: 10.0.x - name: Install dependencies run: dotnet restore diff --git a/.github/workflows/build-test-debug.yml b/.github/workflows/build-test-debug.yml index b9f2796113..e850606703 100644 --- a/.github/workflows/build-test-debug.yml +++ b/.github/workflows/build-test-debug.yml @@ -36,7 +36,7 @@ jobs: - name: Setup .NET Core uses: actions/setup-dotnet@v4.1.0 with: - dotnet-version: 9.0.x + dotnet-version: 10.0.x - name: Install dependencies run: dotnet restore diff --git a/.github/workflows/publish-testing.yml b/.github/workflows/publish-testing.yml index 7a792ed2df..1b1344315a 100644 --- a/.github/workflows/publish-testing.yml +++ b/.github/workflows/publish-testing.yml @@ -20,7 +20,7 @@ jobs: - name: Setup .NET Core uses: actions/setup-dotnet@v3.2.0 with: - dotnet-version: 9.0.x + dotnet-version: 10.0.x - name: Get Engine Tag run: | diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 968782fd96..aaadeefd85 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -47,7 +47,7 @@ jobs: - name: Setup .NET Core uses: actions/setup-dotnet@v4.1.0 with: - dotnet-version: 9.0.x + dotnet-version: 10.0.x - name: Get Engine Tag run: | diff --git a/.github/workflows/test-packaging.yml b/.github/workflows/test-packaging.yml index f8ae6092e6..30735fc828 100644 --- a/.github/workflows/test-packaging.yml +++ b/.github/workflows/test-packaging.yml @@ -65,7 +65,7 @@ jobs: - name: Setup .NET Core uses: actions/setup-dotnet@v4.1.0 with: - dotnet-version: 9.0.x + dotnet-version: 10.0.x - name: Install dependencies run: dotnet restore diff --git a/.github/workflows/update-wiki.yml b/.github/workflows/update-wiki.yml index 898e694934..cdad918b5b 100644 --- a/.github/workflows/update-wiki.yml +++ b/.github/workflows/update-wiki.yml @@ -6,13 +6,10 @@ on: branches: [ master, jsondump ] paths: - '.github/workflows/update-wiki.yml' - - 'Content.Shared/Chemistry/**.cs' - - 'Content.Server/Chemistry/**.cs' - - 'Content.Server/GuideGenerator/**.cs' - - 'Content.Server/Corvax/GuideGenerator/**.cs' - - 'Resources/Prototypes/Reagents/**.yml' - - 'Resources/Prototypes/Chemistry/**.yml' - - 'Resources/Prototypes/Recipes/Reactions/**.yml' + - 'Content.Shared/**' + - 'Content.Server/**' + - 'Content.Client/**' + - 'Resources/**' - 'RobustToolbox/' jobs: @@ -51,42 +48,50 @@ jobs: run: dotnet ./bin/Content.Server/Content.Server.dll --cvar autogen.destination_file=prototypes.json continue-on-error: true - - name: Upload chem_prototypes.json to wiki - uses: jtmullen/mediawiki-edit-action@v0.1.1 - with: - wiki_text_file: ./bin/Content.Server/data/chem_prototypes.json - edit_summary: Update chem_prototypes.json via GitHub Actions - page_name: "${{ secrets.WIKI_PAGE_ROOT }}/chem_prototypes.json" - api_url: ${{ secrets.WIKI_ROOT_URL }}/api.php - username: ${{ secrets.WIKI_BOT_USER }} - password: ${{ secrets.WIKI_BOT_PASS }} + # Проходит по всем JSON-файлам в директории BASE и загружает каждый файл как страницу в MediaWiki. + # Имя страницы формируется из относительного пути к файлу. + - name: Upload JSON files to wiki + shell: bash + run: | + set -euo pipefail - - name: Upload react_prototypes.json to wiki - uses: jtmullen/mediawiki-edit-action@v0.1.1 - with: - wiki_text_file: ./bin/Content.Server/data/react_prototypes.json - edit_summary: Update react_prototypes.json via GitHub Actions - page_name: "${{ secrets.WIKI_PAGE_ROOT }}/react_prototypes.json" - api_url: ${{ secrets.WIKI_ROOT_URL }}/api.php - username: ${{ secrets.WIKI_BOT_USER }} - password: ${{ secrets.WIKI_BOT_PASS }} + BASE="./bin/Content.Server/data" + ROOT="${{ secrets.WIKI_PAGE_ROOT }}" + API="${{ secrets.WIKI_ROOT_URL }}/api.php" + USER="${{ secrets.WIKI_BOT_USER }}" + PASS="${{ secrets.WIKI_BOT_PASS }}" - - name: Upload entity_prototypes.json to wiki - uses: jtmullen/mediawiki-edit-action@v0.1.1 - with: - wiki_text_file: ./bin/Content.Server/data/entity_prototypes.json - edit_summary: Update entity_prototypes.json via GitHub Actions - page_name: "${{ secrets.WIKI_PAGE_ROOT }}/entity_prototypes.json" - api_url: ${{ secrets.WIKI_ROOT_URL }}/api.php - username: ${{ secrets.WIKI_BOT_USER }} - password: ${{ secrets.WIKI_BOT_PASS }} + API="$(printf "%s" "$API" | tr -d '\r\n' | sed 's/[[:space:]]*$//')" + USER="$(printf "%s" "$USER" | tr -d '\r\n')" + PASS="$(printf "%s" "$PASS" | tr -d '\r\n')" + ROOT="$(printf "%s" "$ROOT" | tr -d '\r\n' | sed 's/[[:space:]]*$//')" - - name: Upload mealrecipes_prototypes.json to wiki - uses: jtmullen/mediawiki-edit-action@v0.1.1 - with: - wiki_text_file: ./bin/Content.Server/data/mealrecipes_prototypes.json - edit_summary: Update mealrecipes_prototypes.json via GitHub Actions - page_name: "${{ secrets.WIKI_PAGE_ROOT }}/mealrecipes_prototypes.json" - api_url: ${{ secrets.WIKI_ROOT_URL }}/api.php - username: ${{ secrets.WIKI_BOT_USER }} - password: ${{ secrets.WIKI_BOT_PASS }} + cookiejar="$(mktemp)" + trap 'rm -f "$cookiejar"' EXIT + + login_token=$(curl -sS -c "$cookiejar" --data "action=query&meta=tokens&type=login&format=json" "$API" | jq -r '.query.tokens.logintoken') + curl -sS -c "$cookiejar" -b "$cookiejar" \ + --data-urlencode "action=login" \ + --data-urlencode "lgname=$USER" \ + --data-urlencode "lgpassword=$PASS" \ + --data-urlencode "lgtoken=$login_token" \ + --data-urlencode "format=json" \ + "$API" > /dev/null + + find "$BASE" -type f -name '*.json' | while IFS= read -r file; do + rel="${file#$BASE/}" + rel="$(printf "%s" "$rel" | tr -d '\r\n' | sed 's/:/_/g')" + page="$ROOT/$rel" + echo "Uploading $rel → $page" + + token=$(curl -sS -b "$cookiejar" --data "action=query&meta=tokens&format=json" "$API" | jq -r '.query.tokens.csrftoken') + + curl -sS -b "$cookiejar" \ + --data-urlencode "action=edit" \ + --data-urlencode "title=$page" \ + --data-urlencode "summary=Update $rel via GitHub Actions" \ + --data-urlencode "text@${file}" \ + --data-urlencode "token=$token" \ + --data-urlencode "format=json" \ + "$API" | jq -r '.' + done diff --git a/.github/workflows/yaml-linter.yml b/.github/workflows/yaml-linter.yml index edc00b2b3b..50057ccfe6 100644 --- a/.github/workflows/yaml-linter.yml +++ b/.github/workflows/yaml-linter.yml @@ -29,7 +29,7 @@ jobs: - name: Setup .NET Core uses: actions/setup-dotnet@v4.1.0 with: - dotnet-version: 9.0.x + dotnet-version: 10.0.x - name: Install dependencies run: dotnet restore - name: Build diff --git a/.gitignore b/.gitignore index 5c7244e5e1..ce2b66c868 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +# MSbuild binlog files +*.binlog + ## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. diff --git a/BuildChecker/git_helper.py b/BuildChecker/git_helper.py index bd6603bd34..4e42b1e70e 100644 --- a/BuildChecker/git_helper.py +++ b/BuildChecker/git_helper.py @@ -11,7 +11,7 @@ import time from pathlib import Path from typing import List -SOLUTION_PATH = Path("..") / "SpaceStation14.sln" +SOLUTION_PATH = Path("..") / "SpaceStation14.slnx" # If this doesn't match the saved version we overwrite them all. CURRENT_HOOKS_VERSION = "4" QUIET = len(sys.argv) == 2 and sys.argv[1] == "--quiet" diff --git a/Content.Benchmarks/Content.Benchmarks.csproj b/Content.Benchmarks/Content.Benchmarks.csproj index c3b60a1c69..8d4dfa31bd 100644 --- a/Content.Benchmarks/Content.Benchmarks.csproj +++ b/Content.Benchmarks/Content.Benchmarks.csproj @@ -1,17 +1,20 @@  - - $(TargetFramework) ..\bin\Content.Benchmarks\ - false false Exe true - 12 + false + disable + + + + + @@ -19,10 +22,12 @@ - - - - - + + + + + + + diff --git a/Content.Benchmarks/HeatCapacityBenchmark.cs b/Content.Benchmarks/HeatCapacityBenchmark.cs new file mode 100644 index 0000000000..cef5bc10c7 --- /dev/null +++ b/Content.Benchmarks/HeatCapacityBenchmark.cs @@ -0,0 +1,83 @@ +using System.Threading.Tasks; +using BenchmarkDotNet.Attributes; +using Content.IntegrationTests; +using Content.IntegrationTests.Pair; +using Content.Server.Atmos.EntitySystems; +using Content.Shared.Atmos; +using Robust.Shared; +using Robust.Shared.Analyzers; +using Robust.Shared.GameObjects; + +namespace Content.Benchmarks; + +[Virtual] +[GcServer(true)] +[MemoryDiagnoser] +public class HeatCapacityBenchmark +{ + private TestPair _pair = default!; + private IEntityManager _sEntMan = default!; + private IEntityManager _cEntMan = default!; + private Client.Atmos.EntitySystems.AtmosphereSystem _cAtmos = default!; + private AtmosphereSystem _sAtmos = default!; + private GasMixture _mix; + + [GlobalSetup] + public async Task SetupAsync() + { + ProgramShared.PathOffset = "../../../../"; + PoolManager.Startup(); + _pair = await PoolManager.GetServerClient(); + await _pair.Connect(); + _cEntMan = _pair.Client.ResolveDependency(); + _sEntMan = _pair.Server.ResolveDependency(); + _cAtmos = _cEntMan.System(); + _sAtmos = _sEntMan.System(); + + const float volume = 2500f; + const float temperature = 293.15f; + + const float o2 = 12.3f; + const float n2 = 45.6f; + const float co2 = 0.42f; + const float plasma = 0.05f; + + _mix = new GasMixture(volume) { Temperature = temperature }; + + _mix.AdjustMoles(Gas.Oxygen, o2); + _mix.AdjustMoles(Gas.Nitrogen, n2); + _mix.AdjustMoles(Gas.CarbonDioxide, co2); + _mix.AdjustMoles(Gas.Plasma, plasma); + } + + [Benchmark] + public async Task ClientHeatCapacityBenchmark() + { + await _pair.Client.WaitPost(delegate + { + for (var i = 0; i < 10000; i++) + { + _cAtmos.GetHeatCapacity(_mix, applyScaling: true); + } + }); + } + + [Benchmark] + public async Task ServerHeatCapacityBenchmark() + { + await _pair.Server.WaitPost(delegate + { + for (var i = 0; i < 10000; i++) + { + _sAtmos.GetHeatCapacity(_mix, applyScaling: true); + } + }); + } + + [GlobalCleanup] + public async Task CleanupAsync() + { + await _pair.DisposeAsync(); + PoolManager.Shutdown(); + } +} diff --git a/Content.Client/Administration/AdminNameOverlay.cs b/Content.Client/Administration/AdminNameOverlay.cs index abeed65732..d1a9f6f7a7 100644 --- a/Content.Client/Administration/AdminNameOverlay.cs +++ b/Content.Client/Administration/AdminNameOverlay.cs @@ -134,7 +134,7 @@ internal sealed class AdminNameOverlay : Overlay ? null : _prototypeManager.Index(playerInfo.RoleProto.Value); - var roleName = Loc.GetString(rolePrototype?.Name ?? RoleTypePrototype.FallbackName); + var roleName = rolePrototype?.Name ?? RoleTypePrototype.FallbackName; var roleColor = rolePrototype?.Color ?? RoleTypePrototype.FallbackColor; var roleSymbol = rolePrototype?.Symbol ?? RoleTypePrototype.FallbackSymbol; @@ -213,7 +213,7 @@ internal sealed class AdminNameOverlay : Overlay { color = Color.GreenYellow; color.A = alpha; - args.ScreenHandle.DrawString(_font, screenCoordinates + currentOffset, Loc.GetString(playerInfo.StartingJob), uiScale, playerInfo.Connected ? color : colorDisconnected); + args.ScreenHandle.DrawString(_font, screenCoordinates + currentOffset, playerInfo.StartingJob, uiScale, playerInfo.Connected ? color : colorDisconnected); currentOffset += lineoffset; } @@ -241,7 +241,7 @@ internal sealed class AdminNameOverlay : Overlay color = roleColor; symbol = IsFiltered(playerInfo.RoleProto) ? symbol : string.Empty; text = IsFiltered(playerInfo.RoleProto) - ? roleName.ToUpper() + ? Loc.GetString(roleName).ToUpper() : string.Empty; break; case AdminOverlayAntagFormat.Subtype: diff --git a/Content.Client/Atmos/EntitySystems/AtmosphereSystem.Gases.cs b/Content.Client/Atmos/EntitySystems/AtmosphereSystem.Gases.cs new file mode 100644 index 0000000000..17b994e64f --- /dev/null +++ b/Content.Client/Atmos/EntitySystems/AtmosphereSystem.Gases.cs @@ -0,0 +1,35 @@ +using System.Runtime.CompilerServices; +using Content.Shared.Atmos; + +namespace Content.Client.Atmos.EntitySystems; + +public sealed partial class AtmosphereSystem +{ + /* + Partial class for operations involving GasMixtures. + + Any method that is overridden here is usually because the server-sided implementation contains + code that would escape sandbox. As such these methods are overridden here with a safe + implementation. + */ + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + protected override float GetHeatCapacityCalculation(float[] moles, bool space) + { + // Little hack to make space gas mixtures have heat capacity, therefore allowing them to cool down rooms. + if (space && MathHelper.CloseTo(NumericsHelpers.HorizontalAdd(moles), 0f)) + { + return Atmospherics.SpaceHeatCapacity; + } + + // explicit stackalloc call is banned on client tragically. + // the JIT does not stackalloc this during runtime, + // though this isnt the hottest code path so it should be fine + // the gc can eat a little as a treat + var tmp = new float[moles.Length]; + NumericsHelpers.Multiply(moles, GasSpecificHeats, tmp); + // Adjust heat capacity by speedup, because this is primarily what + // determines how quickly gases heat up/cool. + return MathF.Max(NumericsHelpers.HorizontalAdd(tmp), Atmospherics.MinimumHeatCapacity); + } +} diff --git a/Content.Client/Atmos/EntitySystems/AtmosphereSystem.cs b/Content.Client/Atmos/EntitySystems/AtmosphereSystem.cs index 44759372f4..30567abbf7 100644 --- a/Content.Client/Atmos/EntitySystems/AtmosphereSystem.cs +++ b/Content.Client/Atmos/EntitySystems/AtmosphereSystem.cs @@ -5,7 +5,7 @@ using Robust.Shared.GameStates; namespace Content.Client.Atmos.EntitySystems; -public sealed class AtmosphereSystem : SharedAtmosphereSystem +public sealed partial class AtmosphereSystem : SharedAtmosphereSystem { public override void Initialize() { diff --git a/Content.Client/BarSign/BarSignSystem.cs b/Content.Client/BarSign/BarSignSystem.cs deleted file mode 100644 index 1ea99864a1..0000000000 --- a/Content.Client/BarSign/BarSignSystem.cs +++ /dev/null @@ -1,53 +0,0 @@ -using Content.Client.BarSign.Ui; -using Content.Shared.BarSign; -using Content.Shared.Power; -using Robust.Client.GameObjects; -using Robust.Shared.Prototypes; - -namespace Content.Client.BarSign; - -public sealed class BarSignSystem : VisualizerSystem -{ - [Dependency] private readonly IPrototypeManager _prototypeManager = default!; - [Dependency] private readonly UserInterfaceSystem _ui = default!; - - public override void Initialize() - { - base.Initialize(); - SubscribeLocalEvent(OnAfterAutoHandleState); - } - - private void OnAfterAutoHandleState(EntityUid uid, BarSignComponent component, ref AfterAutoHandleStateEvent args) - { - if (_ui.TryGetOpenUi(uid, BarSignUiKey.Key, out var bui)) - bui.Update(component.Current); - - UpdateAppearance(uid, component); - } - - protected override void OnAppearanceChange(EntityUid uid, BarSignComponent component, ref AppearanceChangeEvent args) - { - UpdateAppearance(uid, component, args.Component, args.Sprite); - } - - private void UpdateAppearance(EntityUid id, BarSignComponent sign, AppearanceComponent? appearance = null, SpriteComponent? sprite = null) - { - if (!Resolve(id, ref appearance, ref sprite)) - return; - - AppearanceSystem.TryGetData(id, PowerDeviceVisuals.Powered, out var powered, appearance); - - if (powered - && sign.Current != null - && _prototypeManager.Resolve(sign.Current, out var proto)) - { - SpriteSystem.LayerSetSprite((id, sprite), 0, proto.Icon); - sprite.LayerSetShader(0, "unshaded"); - } - else - { - SpriteSystem.LayerSetRsiState((id, sprite), 0, "empty"); - sprite.LayerSetShader(0, null, null); - } - } -} diff --git a/Content.Client/BarSign/BarSignVisualizerSystem.cs b/Content.Client/BarSign/BarSignVisualizerSystem.cs new file mode 100644 index 0000000000..3e641fed70 --- /dev/null +++ b/Content.Client/BarSign/BarSignVisualizerSystem.cs @@ -0,0 +1,30 @@ +using Content.Shared.BarSign; +using Content.Shared.Power; +using Robust.Client.GameObjects; +using Robust.Shared.Prototypes; + +namespace Content.Client.BarSign; + +public sealed class BarSignVisualizerSystem : VisualizerSystem +{ + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + + protected override void OnAppearanceChange(EntityUid uid, BarSignComponent component, ref AppearanceChangeEvent args) + { + AppearanceSystem.TryGetData(uid, PowerDeviceVisuals.Powered, out var powered, args.Component); + AppearanceSystem.TryGetData(uid, BarSignVisuals.BarSignPrototype, out var currentSign, args.Component); + + if (powered + && currentSign != null + && _prototypeManager.Resolve(currentSign, out var proto)) + { + SpriteSystem.LayerSetSprite((uid, args.Sprite), 0, proto.Icon); + args.Sprite?.LayerSetShader(0, "unshaded"); + } + else + { + SpriteSystem.LayerSetRsiState((uid, args.Sprite), 0, "empty"); + args.Sprite?.LayerSetShader(0, null, null); + } + } +} diff --git a/Content.Client/BarSign/Ui/BarSignBoundUserInterface.cs b/Content.Client/BarSign/Ui/BarSignBoundUserInterface.cs index fe07f0f1d1..8265877edf 100644 --- a/Content.Client/BarSign/Ui/BarSignBoundUserInterface.cs +++ b/Content.Client/BarSign/Ui/BarSignBoundUserInterface.cs @@ -19,32 +19,27 @@ public sealed class BarSignBoundUserInterface(EntityUid owner, Enum uiKey) : Bou var sign = EntMan.GetComponentOrNull(Owner)?.Current is { } current ? _prototype.Index(current) : null; - var allSigns = Shared.BarSign.BarSignSystem.GetAllBarSigns(_prototype) + var allSigns = BarSignSystem.GetAllBarSigns(_prototype) .OrderBy(p => Loc.GetString(p.Name)) .ToList(); _menu = new(sign, allSigns); _menu.OnSignSelected += id => { - SendMessage(new SetBarSignMessage(id)); + SendPredictedMessage(new SetBarSignMessage(id)); }; _menu.OnClose += Close; _menu.OpenCentered(); } - public void Update(ProtoId? sign) + public override void Update() { - if (_prototype.Resolve(sign, out var signPrototype)) - _menu?.UpdateState(signPrototype); - } - - protected override void Dispose(bool disposing) - { - base.Dispose(disposing); - if (!disposing) + if (!EntMan.TryGetComponent(Owner, out var signComp)) return; - _menu?.Dispose(); + + if (_prototype.Resolve(signComp.Current, out var signPrototype)) + _menu?.UpdateState(signPrototype); } } diff --git a/Content.Client/Cargo/UI/BountyEntry.xaml.cs b/Content.Client/Cargo/UI/BountyEntry.xaml.cs index d813f70ff4..bac7d84bf7 100644 --- a/Content.Client/Cargo/UI/BountyEntry.xaml.cs +++ b/Content.Client/Cargo/UI/BountyEntry.xaml.cs @@ -7,7 +7,6 @@ using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.XAML; using Robust.Shared.Prototypes; using Robust.Shared.Timing; -using Serilog; namespace Content.Client.Cargo.UI; diff --git a/Content.Client/Chemistry/EntitySystems/HyposprayStatusControlSystem.cs b/Content.Client/Chemistry/EntitySystems/HyposprayStatusControlSystem.cs deleted file mode 100644 index 4dfc8506d2..0000000000 --- a/Content.Client/Chemistry/EntitySystems/HyposprayStatusControlSystem.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Content.Client.Chemistry.UI; -using Content.Client.Items; -using Content.Shared.Chemistry.Components; -using Content.Shared.Chemistry.EntitySystems; - -namespace Content.Client.Chemistry.EntitySystems; - -public sealed class HyposprayStatusControlSystem : EntitySystem -{ - [Dependency] private readonly SharedSolutionContainerSystem _solutionContainers = default!; - public override void Initialize() - { - base.Initialize(); - Subs.ItemStatus(ent => new HyposprayStatusControl(ent, _solutionContainers)); - } -} diff --git a/Content.Client/Chemistry/EntitySystems/InjectorStatusControlSystem.cs b/Content.Client/Chemistry/EntitySystems/InjectorStatusControlSystem.cs new file mode 100644 index 0000000000..ca8685eb3e --- /dev/null +++ b/Content.Client/Chemistry/EntitySystems/InjectorStatusControlSystem.cs @@ -0,0 +1,20 @@ +using Content.Client.Chemistry.UI; +using Content.Client.Items; +using Content.Shared.Chemistry.Components; +using Content.Shared.Chemistry.EntitySystems; +using Robust.Shared.Prototypes; + +namespace Content.Client.Chemistry.EntitySystems; + +public sealed class InjectorStatusControlSystem : EntitySystem +{ + [Dependency] private readonly SharedSolutionContainerSystem _solutionContainers = default!; + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + + + public override void Initialize() + { + base.Initialize(); + Subs.ItemStatus(injector => new InjectorStatusControl(injector, _solutionContainers, _prototypeManager)); + } +} diff --git a/Content.Client/Chemistry/EntitySystems/InjectorSystem.cs b/Content.Client/Chemistry/EntitySystems/InjectorSystem.cs deleted file mode 100644 index 58cb5330a2..0000000000 --- a/Content.Client/Chemistry/EntitySystems/InjectorSystem.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Content.Client.Chemistry.UI; -using Content.Client.Items; -using Content.Shared.Chemistry.Components; -using Content.Shared.Chemistry.EntitySystems; - -namespace Content.Client.Chemistry.EntitySystems; - -public sealed class InjectorSystem : SharedInjectorSystem -{ - public override void Initialize() - { - base.Initialize(); - - Subs.ItemStatus(ent => new InjectorStatusControl(ent, SolutionContainer)); - } -} diff --git a/Content.Client/Chemistry/UI/ChemMasterBoundUserInterface.cs b/Content.Client/Chemistry/UI/ChemMasterBoundUserInterface.cs index a669a8da4c..d0a9f5644c 100644 --- a/Content.Client/Chemistry/UI/ChemMasterBoundUserInterface.cs +++ b/Content.Client/Chemistry/UI/ChemMasterBoundUserInterface.cs @@ -48,6 +48,10 @@ namespace Content.Client.Chemistry.UI (uint) _window.BottleDosage.Value, _window.LabelLine)); _window.BufferSortButton.OnPressed += _ => SendMessage( new ChemMasterSortingTypeCycleMessage()); + _window.OutputBufferDraw.OnPressed += _ => SendMessage( + new ChemMasterOutputDrawSourceMessage(ChemMasterDrawSource.Internal)); + _window.OutputBeakerDraw.OnPressed += _ => SendMessage( + new ChemMasterOutputDrawSourceMessage(ChemMasterDrawSource.External)); for (uint i = 0; i < _window.PillTypeButtons.Length; i++) { diff --git a/Content.Client/Chemistry/UI/ChemMasterWindow.xaml b/Content.Client/Chemistry/UI/ChemMasterWindow.xaml index 5bc640ab44..cc2a199172 100644 --- a/Content.Client/Chemistry/UI/ChemMasterWindow.xaml +++ b/Content.Client/Chemistry/UI/ChemMasterWindow.xaml @@ -79,10 +79,13 @@ -