diff --git a/.github/workflows/benchmarks.yml b/.github/workflows/benchmarks.yml index 84bc855437..302e1b7558 100644 --- a/.github/workflows/benchmarks.yml +++ b/.github/workflows/benchmarks.yml @@ -1,4 +1,4 @@ -name: Benchmarks +name: Benchmarks on: workflow_dispatch: schedule: @@ -9,7 +9,7 @@ concurrency: benchmarks jobs: benchmark: name: Run Benchmarks - runs-on: ubuntu-latest + runs-on: [self-hosted] steps: - uses: actions/checkout@v4.2.2 with: diff --git a/.github/workflows/build-docfx.yml b/.github/workflows/build-docfx.yml index 1f010b7291..8dd7c45a3c 100644 --- a/.github/workflows/build-docfx.yml +++ b/.github/workflows/build-docfx.yml @@ -6,7 +6,7 @@ on: jobs: docfx: - runs-on: ubuntu-latest + runs-on: [self-hosted] steps: - uses: actions/checkout@v4.2.2 - name: Setup submodule @@ -18,10 +18,21 @@ jobs: run: | cd RobustToolbox/ git submodule update --init --recursive + - name: Setup .NET Core uses: actions/setup-dotnet@v4.1.0 with: dotnet-version: 9.0.x + env: + DOTNET_INSTALL_DIR: ${{ runner.temp }}/.dotnet + + - name: Set DOTNET_ROOT and PATH + run: | + echo "DOTNET_ROOT=${{ runner.temp }}/.dotnet" >> $GITHUB_ENV + echo "${{ runner.temp }}/.dotnet" >> $GITHUB_PATH + + - name: Check .NET installation + run: dotnet --info - name: Install dependencies run: dotnet restore diff --git a/.github/workflows/build-map-renderer.yml b/.github/workflows/build-map-renderer.yml index be73a66ba8..4cac4c7414 100644 --- a/.github/workflows/build-map-renderer.yml +++ b/.github/workflows/build-map-renderer.yml @@ -1,4 +1,4 @@ -name: Build & Test Map Renderer +name: Build & Test Map Renderer on: push: @@ -37,6 +37,16 @@ jobs: uses: actions/setup-dotnet@v4.1.0 with: dotnet-version: 9.0.x + env: + DOTNET_INSTALL_DIR: ${{ runner.temp }}/.dotnet + + - name: Set DOTNET_ROOT and PATH + run: | + echo "DOTNET_ROOT=${{ runner.temp }}/.dotnet" >> $GITHUB_ENV + echo "${{ runner.temp }}/.dotnet" >> $GITHUB_PATH + + - name: Check .NET installation + run: dotnet --info - name: Install dependencies run: dotnet restore diff --git a/.github/workflows/build-test-debug.yml b/.github/workflows/build-test-debug.yml index b9f2796113..7c21a5630a 100644 --- a/.github/workflows/build-test-debug.yml +++ b/.github/workflows/build-test-debug.yml @@ -13,7 +13,7 @@ jobs: if: github.actor != 'IanComradeBot' && github.event.pull_request.draft == false strategy: matrix: - os: [ubuntu-latest] + os: [self-hosted] runs-on: ${{ matrix.os }} @@ -37,6 +37,16 @@ jobs: uses: actions/setup-dotnet@v4.1.0 with: dotnet-version: 9.0.x + env: + DOTNET_INSTALL_DIR: ${{ runner.temp }}/.dotnet + + - name: Set DOTNET_ROOT and PATH + run: | + echo "DOTNET_ROOT=${{ runner.temp }}/.dotnet" >> $GITHUB_ENV + echo "${{ runner.temp }}/.dotnet" >> $GITHUB_PATH + + - name: Check .NET installation + run: dotnet --info - name: Install dependencies run: dotnet restore diff --git a/.github/workflows/check-crlf.yml b/.github/workflows/check-crlf.yml index 15e21f3f39..42b369a9c6 100644 --- a/.github/workflows/check-crlf.yml +++ b/.github/workflows/check-crlf.yml @@ -1,4 +1,4 @@ -name: CRLF Check +name: CRLF Check on: pull_request: @@ -8,7 +8,7 @@ jobs: build: name: CRLF Check if: github.event.pull_request.draft == false - runs-on: ubuntu-latest + runs-on: [self-hosted] steps: - uses: actions/checkout@v4.2.2 - name: Check for CRLF diff --git a/.github/workflows/close-master-pr.yml b/.github/workflows/close-master-pr.yml index 6637e464cc..50dbd725e9 100644 --- a/.github/workflows/close-master-pr.yml +++ b/.github/workflows/close-master-pr.yml @@ -6,7 +6,7 @@ on: jobs: run: - runs-on: ubuntu-latest + runs-on: [self-hosted] if: ${{github.head_ref == 'master' || github.head_ref == 'main' || github.head_ref == 'develop'}} steps: diff --git a/.github/workflows/labeler-approve.yml b/.github/workflows/labeler-approve.yml index 15b092aa3b..2fb74135b1 100644 --- a/.github/workflows/labeler-approve.yml +++ b/.github/workflows/labeler-approve.yml @@ -1,4 +1,4 @@ -name: "Labels: Approve" +name: "Labels: Approve" on: pull_request_review: @@ -9,7 +9,7 @@ jobs: permissions: pull-requests: write if: github.event.review.state == 'approved' - runs-on: ubuntu-latest + runs-on: [self-hosted] steps: - uses: actions-ecosystem/action-remove-labels@v1 with: diff --git a/.github/workflows/labeler-changes.yml b/.github/workflows/labeler-changes.yml index e7d8fc45e1..f4f5224075 100644 --- a/.github/workflows/labeler-changes.yml +++ b/.github/workflows/labeler-changes.yml @@ -1,4 +1,4 @@ -name: "Labels: Changes" +name: "Labels: Changes" on: pull_request_review: @@ -9,7 +9,7 @@ jobs: permissions: pull-requests: write if: github.event.review.state == 'changes_requested' - runs-on: ubuntu-latest + runs-on: [self-hosted] steps: - uses: actions-ecosystem/action-add-labels@v1 with: diff --git a/.github/workflows/labeler-needsreview.yml b/.github/workflows/labeler-needsreview.yml index d3373ce91d..04feec8db5 100644 --- a/.github/workflows/labeler-needsreview.yml +++ b/.github/workflows/labeler-needsreview.yml @@ -1,4 +1,4 @@ -name: "Labels: Review" +name: "Labels: Review" on: pull_request_target: @@ -6,7 +6,7 @@ on: jobs: add_label: - runs-on: ubuntu-latest + runs-on: [self-hosted] steps: - uses: actions-ecosystem/action-add-labels@v1 with: diff --git a/.github/workflows/labeler-pr.yml b/.github/workflows/labeler-pr.yml index 92f6339f20..30d93c020a 100644 --- a/.github/workflows/labeler-pr.yml +++ b/.github/workflows/labeler-pr.yml @@ -1,4 +1,4 @@ -name: "Labels: PR" +name: "Labels: PR" on: - pull_request_target diff --git a/.github/workflows/labeler-stable.yml b/.github/workflows/labeler-stable.yml index f6fd2033a1..db976909b5 100644 --- a/.github/workflows/labeler-stable.yml +++ b/.github/workflows/labeler-stable.yml @@ -9,7 +9,7 @@ on: jobs: add_label: - runs-on: ubuntu-latest + runs-on: [self-hosted] steps: - uses: actions-ecosystem/action-add-labels@v1 with: diff --git a/.github/workflows/labeler-staging.yml b/.github/workflows/labeler-staging.yml index b46a198aef..f32db21e2c 100644 --- a/.github/workflows/labeler-staging.yml +++ b/.github/workflows/labeler-staging.yml @@ -9,7 +9,7 @@ on: jobs: add_label: - runs-on: ubuntu-latest + runs-on: [self-hosted] steps: - uses: actions-ecosystem/action-add-labels@v1 with: diff --git a/.github/workflows/labeler-untriaged.yml b/.github/workflows/labeler-untriaged.yml index b6b383161c..b9a23781f0 100644 --- a/.github/workflows/labeler-untriaged.yml +++ b/.github/workflows/labeler-untriaged.yml @@ -1,4 +1,4 @@ -name: "Labels: Untriaged" +name: "Labels: Untriaged" on: issues: diff --git a/.github/workflows/no-submodule-update.yml b/.github/workflows/no-submodule-update.yml index f2a9d72e37..b1d3b25460 100644 --- a/.github/workflows/no-submodule-update.yml +++ b/.github/workflows/no-submodule-update.yml @@ -8,7 +8,7 @@ on: jobs: this_aint_right: name: Submodule update in pr found - runs-on: ubuntu-latest + runs-on: [self-hosted] steps: - name: Fail run: exit 1 diff --git a/.github/workflows/publish-public.yml b/.github/workflows/publish-public.yml index 529c6701b3..51581111d6 100644 --- a/.github/workflows/publish-public.yml +++ b/.github/workflows/publish-public.yml @@ -10,7 +10,7 @@ on: jobs: build: - runs-on: ubuntu-latest + runs-on: [self-hosted] steps: # - name: Install dependencies @@ -24,6 +24,16 @@ jobs: uses: actions/setup-dotnet@v4.1.0 with: dotnet-version: 9.0.x + env: + DOTNET_INSTALL_DIR: ${{ runner.temp }}/.dotnet + + - name: Set DOTNET_ROOT and PATH + run: | + echo "DOTNET_ROOT=${{ runner.temp }}/.dotnet" >> $GITHUB_ENV + echo "${{ runner.temp }}/.dotnet" >> $GITHUB_PATH + + - name: Check .NET installation + run: dotnet --info - name: Get Engine Tag run: | diff --git a/.github/workflows/publish-testing.yml b/.github/workflows/publish-testing.yml index 6dacef1324..173943b75b 100644 --- a/.github/workflows/publish-testing.yml +++ b/.github/workflows/publish-testing.yml @@ -1,4 +1,4 @@ -name: Publish Testing +name: Publish Testing concurrency: group: publish-testing @@ -11,16 +11,27 @@ on: jobs: build: - runs-on: ubuntu-latest + runs-on: [self-hosted] steps: - uses: actions/checkout@v3.6.0 with: submodules: 'recursive' + - name: Setup .NET Core - uses: actions/setup-dotnet@v3.2.0 + uses: actions/setup-dotnet@v4.1.0 with: dotnet-version: 9.0.x + env: + DOTNET_INSTALL_DIR: ${{ runner.temp }}/.dotnet + + - name: Set DOTNET_ROOT and PATH + run: | + echo "DOTNET_ROOT=${{ runner.temp }}/.dotnet" >> $GITHUB_ENV + echo "${{ runner.temp }}/.dotnet" >> $GITHUB_PATH + + - name: Check .NET installation + run: dotnet --info - name: Get Engine Tag run: | diff --git a/.github/workflows/rsi-diff.yml b/.github/workflows/rsi-diff.yml index 390ddcda6e..0019e389d5 100644 --- a/.github/workflows/rsi-diff.yml +++ b/.github/workflows/rsi-diff.yml @@ -8,7 +8,7 @@ on: jobs: diff: name: Diff - runs-on: ubuntu-latest + runs-on: [self-hosted] steps: - name: Checkout uses: actions/checkout@v4.2.2 diff --git a/.github/workflows/test-packaging.yml b/.github/workflows/test-packaging.yml index 4555b521ee..2dc2998bc9 100644 --- a/.github/workflows/test-packaging.yml +++ b/.github/workflows/test-packaging.yml @@ -1,4 +1,4 @@ -name: Test Packaging +name: Test Packaging on: push: @@ -30,7 +30,7 @@ jobs: build: name: Test Packaging if: github.actor != 'IanComradeBot' && github.event.pull_request.draft == false - runs-on: ubuntu-latest + runs-on: [self-hosted] steps: - name: Checkout Master @@ -66,6 +66,16 @@ jobs: uses: actions/setup-dotnet@v4.1.0 with: dotnet-version: 9.0.x + env: + DOTNET_INSTALL_DIR: ${{ runner.temp }}/.dotnet + + - name: Set DOTNET_ROOT and PATH + run: | + echo "DOTNET_ROOT=${{ runner.temp }}/.dotnet" >> $GITHUB_ENV + echo "${{ runner.temp }}/.dotnet" >> $GITHUB_PATH + + - name: Check .NET installation + run: dotnet --info - name: Install dependencies run: dotnet restore diff --git a/.github/workflows/update-credits.yml b/.github/workflows/update-credits.yml index eb609556d4..e4a5582534 100644 --- a/.github/workflows/update-credits.yml +++ b/.github/workflows/update-credits.yml @@ -7,7 +7,7 @@ on: jobs: get_credits: - runs-on: ubuntu-latest + runs-on: [self-hosted] # Hey there fork dev! If you like to include your own contributors in this then you can probably just change this to your own repo # Do this in dump_github_contributors.ps1 too into your own repo if: github.repository == 'space-wizards/space-station-14' diff --git a/.github/workflows/update-wiki.yml b/.github/workflows/update-wiki.yml index 898e694934..e19e68f73d 100644 --- a/.github/workflows/update-wiki.yml +++ b/.github/workflows/update-wiki.yml @@ -18,7 +18,7 @@ on: jobs: update-wiki: name: Build and Publish JSON blobs to wiki - runs-on: ubuntu-latest + runs-on: [self-hosted] steps: - name: Checkout Master @@ -40,6 +40,16 @@ jobs: uses: actions/setup-dotnet@v4.1.0 with: dotnet-version: 9.0.x + env: + DOTNET_INSTALL_DIR: ${{ runner.temp }}/.dotnet + + - name: Set DOTNET_ROOT and PATH + run: | + echo "DOTNET_ROOT=${{ runner.temp }}/.dotnet" >> $GITHUB_ENV + echo "${{ runner.temp }}/.dotnet" >> $GITHUB_PATH + + - name: Check .NET installation + run: dotnet --info - name: Install Dependencies run: dotnet restore diff --git a/.github/workflows/validate-rgas.yml b/.github/workflows/validate-rgas.yml index 1646b16c2c..89d3e93859 100644 --- a/.github/workflows/validate-rgas.yml +++ b/.github/workflows/validate-rgas.yml @@ -10,7 +10,7 @@ jobs: yaml-schema-validation: name: YAML RGA schema validator if: github.actor != 'IanComradeBot' && github.event.pull_request.draft == false - runs-on: ubuntu-latest + runs-on: [self-hosted] steps: - uses: actions/checkout@v4.2.2 - name: Setup Submodule diff --git a/.github/workflows/validate-rsis.yml b/.github/workflows/validate-rsis.yml index 84ba849c19..6a80e74d0e 100644 --- a/.github/workflows/validate-rsis.yml +++ b/.github/workflows/validate-rsis.yml @@ -11,7 +11,7 @@ on: jobs: validate_rsis: name: Validate RSIs - runs-on: ubuntu-latest + runs-on: [self-hosted] steps: - uses: actions/checkout@v4.2.2 - name: Setup Submodule diff --git a/.github/workflows/validate_mapfiles.yml b/.github/workflows/validate_mapfiles.yml index 9eef03a7c8..dce10eb855 100644 --- a/.github/workflows/validate_mapfiles.yml +++ b/.github/workflows/validate_mapfiles.yml @@ -10,7 +10,7 @@ jobs: yaml-schema-validation: name: YAML map schema validator if: github.actor != 'IanComradeBot' && github.event.pull_request.draft == false - runs-on: ubuntu-latest + runs-on: [self-hosted] steps: - uses: actions/checkout@v4.2.2 - name: Setup Submodule diff --git a/.github/workflows/yaml-linter.yml b/.github/workflows/yaml-linter.yml index edc00b2b3b..d28bc52b7c 100644 --- a/.github/workflows/yaml-linter.yml +++ b/.github/workflows/yaml-linter.yml @@ -11,7 +11,7 @@ jobs: build: name: YAML Linter if: github.actor != 'IanComradeBot' && github.event.pull_request.draft == false - runs-on: ubuntu-latest + runs-on: [self-hosted] steps: - uses: actions/checkout@v4.2.2 - name: Delete sponsor-tiers YAML file diff --git a/Content.Benchmarks/PvsBenchmark.cs b/Content.Benchmarks/PvsBenchmark.cs index 1edbcb6448..51a013539e 100644 --- a/Content.Benchmarks/PvsBenchmark.cs +++ b/Content.Benchmarks/PvsBenchmark.cs @@ -6,7 +6,6 @@ using BenchmarkDotNet.Attributes; using Content.IntegrationTests; using Content.IntegrationTests.Pair; using Content.Server.Mind; -using Content.Server.Warps; using Content.Shared.Warps; using Robust.Shared; using Robust.Shared.Analyzers; diff --git a/Content.Client/Actions/UI/ActionAlertTooltip.cs b/Content.Client/Actions/UI/ActionAlertTooltip.cs index 2425cdefb9..664a67b406 100644 --- a/Content.Client/Actions/UI/ActionAlertTooltip.cs +++ b/Content.Client/Actions/UI/ActionAlertTooltip.cs @@ -21,7 +21,7 @@ namespace Content.Client.Actions.UI /// public (TimeSpan Start, TimeSpan End)? Cooldown { get; set; } - public ActionAlertTooltip(FormattedMessage name, FormattedMessage? desc, string? requires = null, FormattedMessage? charges = null) + public ActionAlertTooltip(FormattedMessage name, FormattedMessage? desc, string? requires = null) { _gameTiming = IoCManager.Resolve(); @@ -52,17 +52,6 @@ namespace Content.Client.Actions.UI vbox.AddChild(description); } - if (charges != null && !string.IsNullOrWhiteSpace(charges.ToString())) - { - var chargesLabel = new RichTextLabel - { - MaxWidth = TooltipTextMaxWidth, - StyleClasses = { StyleNano.StyleClassTooltipActionCharges } - }; - chargesLabel.SetMessage(charges); - vbox.AddChild(chargesLabel); - } - vbox.AddChild(_cooldownLabel = new RichTextLabel { MaxWidth = TooltipTextMaxWidth, diff --git a/Content.Client/Administration/Components/HeadstandComponent.cs b/Content.Client/Administration/Components/HeadstandComponent.cs deleted file mode 100644 index a4e3bfc5aa..0000000000 --- a/Content.Client/Administration/Components/HeadstandComponent.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Content.Shared.Administration.Components; -using Robust.Shared.GameStates; - -namespace Content.Client.Administration.Components; - -[RegisterComponent] -public sealed partial class HeadstandComponent : SharedHeadstandComponent -{ - -} diff --git a/Content.Client/Administration/Systems/HeadstandSystem.cs b/Content.Client/Administration/Systems/HeadstandSystem.cs index d0634e4ddd..8ab337f3cc 100644 --- a/Content.Client/Administration/Systems/HeadstandSystem.cs +++ b/Content.Client/Administration/Systems/HeadstandSystem.cs @@ -1,4 +1,4 @@ -using Content.Client.Administration.Components; +using Content.Shared.Administration.Components; using Robust.Client.GameObjects; namespace Content.Client.Administration.Systems; diff --git a/Content.Client/Administration/UI/Tabs/ObjectsTab/ObjectsTab.xaml.cs b/Content.Client/Administration/UI/Tabs/ObjectsTab/ObjectsTab.xaml.cs index 59e0e6040b..de9ccbbf50 100644 --- a/Content.Client/Administration/UI/Tabs/ObjectsTab/ObjectsTab.xaml.cs +++ b/Content.Client/Administration/UI/Tabs/ObjectsTab/ObjectsTab.xaml.cs @@ -76,7 +76,7 @@ public sealed partial class ObjectsTab : Control switch (selection) { case ObjectsTabSelection.Stations: - entities.AddRange(_entityManager.EntitySysManager.GetEntitySystem().Stations); + entities.AddRange(_entityManager.EntitySysManager.GetEntitySystem().GetStationNames()); break; case ObjectsTabSelection.Grids: { diff --git a/Content.Client/Animals/Systems/ParrotMemorySystem.cs b/Content.Client/Animals/Systems/ParrotMemorySystem.cs new file mode 100644 index 0000000000..cdf62a4eae --- /dev/null +++ b/Content.Client/Animals/Systems/ParrotMemorySystem.cs @@ -0,0 +1,5 @@ +using Content.Shared.Animals.Systems; + +namespace Content.Client.Animals.Systems; + +public sealed class ParrotMemorySystem : SharedParrotMemorySystem; diff --git a/Content.Client/Anomaly/Effects/ClientInnerBodySystem.cs b/Content.Client/Anomaly/Effects/ClientInnerBodySystem.cs index 15ebc8a993..d96980fb1d 100644 --- a/Content.Client/Anomaly/Effects/ClientInnerBodySystem.cs +++ b/Content.Client/Anomaly/Effects/ClientInnerBodySystem.cs @@ -1,6 +1,6 @@ using Content.Shared.Anomaly.Components; using Content.Shared.Anomaly.Effects; -using Content.Shared.Body.Components; +using Content.Shared.Humanoid; using Robust.Client.GameObjects; namespace Content.Client.Anomaly.Effects; @@ -25,9 +25,8 @@ public sealed class ClientInnerBodyAnomalySystem : SharedInnerBodyAnomalySystem var index = _sprite.LayerMapReserve((ent.Owner, sprite), ent.Comp.LayerMap); - if (TryComp(ent, out var body) && - body.Prototype is not null && - ent.Comp.SpeciesSprites.TryGetValue(body.Prototype.Value, out var speciesSprite)) + if (TryComp(ent, out var humanoidAppearance) && + ent.Comp.SpeciesSprites.TryGetValue(humanoidAppearance.Species, out var speciesSprite)) { _sprite.LayerSetSprite((ent.Owner, sprite), index, speciesSprite); } diff --git a/Content.Client/Atmos/EntitySystems/PipeColorVisualizerSystem.cs b/Content.Client/Atmos/EntitySystems/PipeColorVisualizerSystem.cs index b23a44e403..5595f441f7 100644 --- a/Content.Client/Atmos/EntitySystems/PipeColorVisualizerSystem.cs +++ b/Content.Client/Atmos/EntitySystems/PipeColorVisualizerSystem.cs @@ -1,46 +1,11 @@ using Content.Client.Atmos.Components; using Robust.Client.GameObjects; -using Content.Client.UserInterface.Systems.Storage.Controls; using Content.Shared.Atmos.Piping; -using Content.Shared.Hands; -using Content.Shared.Atmos.Components; -using Content.Shared.Item; namespace Content.Client.Atmos.EntitySystems; public sealed class PipeColorVisualizerSystem : VisualizerSystem { - [Dependency] private readonly SharedItemSystem _itemSystem = default!; - - public override void Initialize() - { - base.Initialize(); - - SubscribeLocalEvent(OnGetVisuals); - SubscribeLocalEvent(OnDrawInGrid); - } - - /// - /// This method is used to display the color changes of the pipe on the screen.. - /// - private void OnGetVisuals(Entity item, ref GetInhandVisualsEvent args) - { - foreach (var (_, layerData) in args.Layers) - { - if (TryComp(item.Owner, out AtmosPipeColorComponent? pipeColor)) - layerData.Color = pipeColor.Color; - } - } - - /// - /// This method is used to change the pipe's color in a container grid. - /// - private void OnDrawInGrid(Entity item, ref BeforeRenderInGridEvent args) - { - if (TryComp(item.Owner, out AtmosPipeColorComponent? pipeColor)) - args.Color = pipeColor.Color; - } - protected override void OnAppearanceChange(EntityUid uid, PipeColorVisualsComponent component, ref AppearanceChangeEvent args) { if (TryComp(uid, out var sprite) @@ -50,8 +15,6 @@ public sealed class PipeColorVisualizerSystem : VisualizerSystem()) { - _pumpDirection.AddItem(Loc.GetString($"{value}"), (int) value); + _pumpDirection.AddItem(Loc.GetString($"air-alarm-ui-pump-direction-{value.ToString().ToLower()}"), (int) value); } _pumpDirection.SelectId((int) _data.PumpDirection); @@ -72,7 +72,7 @@ public sealed partial class PumpControl : BoxContainer foreach (var value in Enum.GetValues()) { - _pressureCheck.AddItem(Loc.GetString($"{value}"), (int) value); + _pressureCheck.AddItem(Loc.GetString($"air-alarm-ui-pressure-bound-{value.ToString().ToLower()}"), (int) value); } _pressureCheck.SelectId((int) _data.PressureChecks); diff --git a/Content.Client/Atmos/Monitor/UI/Widgets/ScrubberControl.xaml b/Content.Client/Atmos/Monitor/UI/Widgets/ScrubberControl.xaml index 34c1a9dd1a..c26aa2cf6e 100644 --- a/Content.Client/Atmos/Monitor/UI/Widgets/ScrubberControl.xaml +++ b/Content.Client/Atmos/Monitor/UI/Widgets/ScrubberControl.xaml @@ -27,9 +27,15 @@ - + - + + +