Compare commits
7 Commits
ed-05-06-2
...
ed-cla-tes
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
98d904d75f | ||
|
|
13a6bc2920 | ||
|
|
58bb5ce26f | ||
|
|
cf24ec8375 | ||
|
|
1d1133c6d4 | ||
|
|
ca288f1288 | ||
|
|
0afd87163c |
@@ -127,7 +127,6 @@ csharp_indent_braces = false
|
||||
#csharp_indent_case_contents_when_block = true
|
||||
#csharp_indent_labels = one_less_than_current
|
||||
csharp_indent_switch_labels = true
|
||||
xmldoc_indent_text = zeroindent
|
||||
|
||||
# Space preferences
|
||||
csharp_space_after_cast = false
|
||||
@@ -345,9 +344,6 @@ resharper_keep_existing_attribute_arrangement = true
|
||||
resharper_wrap_chained_binary_patterns = chop_if_long
|
||||
resharper_wrap_chained_method_calls = chop_if_long
|
||||
resharper_csharp_trailing_comma_in_multiline_lists = true
|
||||
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}]
|
||||
indent_size = 2
|
||||
|
||||
5
.envrc
5
.envrc
@@ -1,5 +1,4 @@
|
||||
set -e
|
||||
if ! has nix_direnv_version || ! nix_direnv_version 3.0.6; then
|
||||
source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.0.6/direnvrc" "sha256-RYcUJaRMf8oF5LznDrlCXbkOQrywm0HDv1VjYGaJGdM="
|
||||
if ! has nix_direnv_version || ! nix_direnv_version 3.0.4; then
|
||||
source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.0.4/direnvrc" "sha256-DzlYZ33mWF/Gs8DDeyjr8mnVmQGx7ASYqA5WlxwvBG4="
|
||||
fi
|
||||
use flake
|
||||
|
||||
49
.github/CODEOWNERS
vendored
49
.github/CODEOWNERS
vendored
@@ -1,6 +1,45 @@
|
||||
# TheShuEd
|
||||
* @TheShuEd
|
||||
# Last match in file takes precedence.
|
||||
|
||||
# TornadoTechnology
|
||||
*.cs @Tornado-Technology
|
||||
*.xaml @Tornado-Technology
|
||||
# Sorting by path instead of by who added it one day :(
|
||||
# this isn't how codeowners rules work pls read the first comment instead of trying to force a sorting order
|
||||
|
||||
/Resources/ConfigPresets/WizardsDen/ @nikthechampiongr @crazybrain23
|
||||
/Content.*/Administration/ @DrSmugleaf @nikthechampiongr @crazybrain23
|
||||
/Resources/ServerInfo/ @nikthechampiongr @crazybrain23
|
||||
/Resources/ServerInfo/Guidebook/ServerRules/ @nikthechampiongr @crazybrain23
|
||||
|
||||
/Resources/Prototypes/Maps/** @Emisse
|
||||
|
||||
/Resources/Prototypes/Body/ @DrSmugleaf # suffering
|
||||
/Resources/Prototypes/Entities/Mobs/Player/ @DrSmugleaf
|
||||
/Resources/Prototypes/Entities/Mobs/Species/ @DrSmugleaf
|
||||
/Resources/Prototypes/Guidebook/rules.yml @nikthechampiongr @crazybrain23
|
||||
/Content.*/Body/ @DrSmugleaf
|
||||
/Content.YAMLLinter @DrSmugleaf
|
||||
/Content.Shared/Damage/ @DrSmugleaf
|
||||
|
||||
/Content.*/Anomaly/ @TheShuEd
|
||||
/Resources/Prototypes/Entities/Structures/Specific/anomalies.yml @TheShuEd
|
||||
|
||||
/Content.*/Forensics/ @ficcialfaint
|
||||
|
||||
# SKREEEE
|
||||
/Content.*.Database/ @PJB3005 @DrSmugleaf
|
||||
/Content.Shared.Database/Log*.cs @PJB3005 @DrSmugleaf @nikthechampiongr @crazybrain23
|
||||
/Pow3r/ @PJB3005
|
||||
/Content.Server/Power/Pow3r/ @PJB3005
|
||||
|
||||
# notafet
|
||||
/Content.*/Atmos/ @Partmedia
|
||||
/Content.*/Botany/ @Partmedia
|
||||
|
||||
# Jezi
|
||||
/Content.*/Medical @Jezithyr
|
||||
/Content.*/Body @Jezithyr
|
||||
|
||||
# Sloth
|
||||
/Content.*/Audio @metalgearsloth
|
||||
/Content.*/Movement @metalgearsloth
|
||||
/Content.*/NPC @metalgearsloth
|
||||
/Content.*/Shuttles @metalgearsloth
|
||||
/Content.*/Weapons @metalgearsloth
|
||||
|
||||
14
.github/PULL_REQUEST_TEMPLATE.md
vendored
14
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,23 +1,17 @@
|
||||
## About the PR
|
||||
<!-- What did you change in this PR? -->
|
||||
<!-- Что вы изменили в своем пулл реквесте? -->
|
||||
|
||||
## Why / Balance
|
||||
<!-- Why was it changed? Link any discussions or issues here. Please discuss how this would affect game balance. -->
|
||||
<!-- Зачем нужно это изменение? Прикрепите любые обсуждения или проблемы здесь. Опишите, как это повлияет на текущий баланс игры. -->
|
||||
|
||||
## Media
|
||||
<!--
|
||||
PRs which make ingame changes (adding clothing, items, new features, etc) are required to have media attached that showcase the changes.
|
||||
Small fixes/refactors are exempt.
|
||||
-->
|
||||
|
||||
**Changelog**
|
||||
<!-- Add a Changelog entry to make players aware of new features or changes that could affect gameplay.
|
||||
Make sure to read the guidelines and take this Changelog template out of the comment block in order for it to show up.
|
||||
Changelog must have a :cl: symbol, so the bot recognizes the changes and adds them to the game's changelog. -->
|
||||
<!--
|
||||
:cl:
|
||||
- add: Added fun!
|
||||
- remove: Removed fun!
|
||||
- tweak: Changed fun!
|
||||
- fix: Fixed fun!
|
||||
Пулл реквесты, которые несут за собой игровые изменения (добавления одежды, предметов и так далее) требуют чтобы вы прикрепили скриншоты или видеоролики, демонстрирующие эти изменения.
|
||||
Небольшие исправления не считаются.
|
||||
-->
|
||||
|
||||
18
.github/workflows/CP14Publish.yml
vendored
18
.github/workflows/CP14Publish.yml
vendored
@@ -1,4 +1,4 @@
|
||||
name: Edge Publish
|
||||
name: Publish
|
||||
|
||||
concurrency:
|
||||
group: publish
|
||||
@@ -10,15 +10,6 @@ jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Install Python dependencies
|
||||
run: sudo apt-get install -y python3-paramiko python3-lxml
|
||||
|
||||
- name: Send POST-request
|
||||
uses: appleboy/ssh-action@master
|
||||
with:
|
||||
@@ -27,10 +18,3 @@ jobs:
|
||||
password: ${{ secrets.BUILD_PASS }}
|
||||
port: 22
|
||||
script: sh update.sh &> /dev/null
|
||||
|
||||
- name: Publish changelog (Discord)
|
||||
continue-on-error: true
|
||||
run: Tools/actions_changelogs_since_last_run.py
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
DISCORD_WEBHOOK_URL: ${{ secrets.CHANGELOG_DISCORD_WEBHOOK }}
|
||||
2
.github/workflows/benchmarks.yml
vendored
2
.github/workflows/benchmarks.yml
vendored
@@ -11,7 +11,7 @@ jobs:
|
||||
name: Run Benchmarks
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4.2.2
|
||||
- uses: actions/checkout@v3.6.0
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
- name: Get Engine version
|
||||
|
||||
4
.github/workflows/build-docfx.yml
vendored
4
.github/workflows/build-docfx.yml
vendored
@@ -8,7 +8,7 @@ jobs:
|
||||
docfx:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4.2.2
|
||||
- uses: actions/checkout@v3.6.0
|
||||
- name: Setup submodule
|
||||
run: |
|
||||
git submodule update --init --recursive
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
cd RobustToolbox/
|
||||
git submodule update --init --recursive
|
||||
- name: Setup .NET Core
|
||||
uses: actions/setup-dotnet@v4.1.0
|
||||
uses: actions/setup-dotnet@v3.2.0
|
||||
with:
|
||||
dotnet-version: 9.0.x
|
||||
|
||||
|
||||
4
.github/workflows/build-map-renderer.yml
vendored
4
.github/workflows/build-map-renderer.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout Master
|
||||
uses: actions/checkout@v4.2.2
|
||||
uses: actions/checkout@v3.6.0
|
||||
|
||||
- name: Setup Submodule
|
||||
run: |
|
||||
@@ -34,7 +34,7 @@ jobs:
|
||||
git submodule update --init --recursive
|
||||
|
||||
- name: Setup .NET Core
|
||||
uses: actions/setup-dotnet@v4.1.0
|
||||
uses: actions/setup-dotnet@v3.2.0
|
||||
with:
|
||||
dotnet-version: 9.0.x
|
||||
|
||||
|
||||
4
.github/workflows/build-test-debug.yml
vendored
4
.github/workflows/build-test-debug.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout Master
|
||||
uses: actions/checkout@v4.2.2
|
||||
uses: actions/checkout@v3.6.0
|
||||
|
||||
- name: Setup Submodule
|
||||
run: |
|
||||
@@ -34,7 +34,7 @@ jobs:
|
||||
git submodule update --init --recursive
|
||||
|
||||
- name: Setup .NET Core
|
||||
uses: actions/setup-dotnet@v4.1.0
|
||||
uses: actions/setup-dotnet@v3.2.0
|
||||
with:
|
||||
dotnet-version: 9.0.x
|
||||
|
||||
|
||||
2
.github/workflows/check-crlf.yml
vendored
2
.github/workflows/check-crlf.yml
vendored
@@ -10,6 +10,6 @@ jobs:
|
||||
if: github.event.pull_request.draft == false
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4.2.2
|
||||
- uses: actions/checkout@v3.6.0
|
||||
- name: Check for CRLF
|
||||
run: Tools/check_crlf.py
|
||||
|
||||
59
.github/workflows/check-trailing-whitespace.yml
vendored
59
.github/workflows/check-trailing-whitespace.yml
vendored
@@ -1,59 +0,0 @@
|
||||
name: Trailing Whitespace Check
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [ opened, reopened, synchronize, ready_for_review ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Trailing Whitespace Check
|
||||
if: github.event.pull_request.draft == false
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4.2.2
|
||||
- name: Get changed text files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@v46.0.5
|
||||
with:
|
||||
files: |
|
||||
**.cs
|
||||
**.yml
|
||||
**.swsl
|
||||
**.json
|
||||
**.py
|
||||
- name: Check for trailing whitespace and EOF newline
|
||||
env:
|
||||
ALL_CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }}
|
||||
run: |
|
||||
has_trailing_whitespace=0
|
||||
has_missing_eof_newline=0
|
||||
|
||||
for file in ${ALL_CHANGED_FILES}; do
|
||||
# Ignore vanilla not CrystallEdge files
|
||||
if [[ "$file" != *CP14* ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
echo "Checking $file"
|
||||
|
||||
# Check for trailing whitespace
|
||||
if grep -qP '[ \t]+$' "$file"; then
|
||||
echo "::error file=$file::Trailing whitespace found"
|
||||
has_trailing_whitespace=1
|
||||
fi
|
||||
|
||||
# Check for missing EOF newline
|
||||
if [ -f "$file" ] && [ -s "$file" ]; then
|
||||
last_char=$(tail -c 1 "$file")
|
||||
if [ "$last_char" != "" ] && [ "$last_char" != $'\n' ]; then
|
||||
echo "::error file=$file::Missing newline at end of file"
|
||||
has_missing_eof_newline=1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$has_trailing_whitespace" -eq 1 ] || [ "$has_missing_eof_newline" -eq 1 ]; then
|
||||
echo "Issues found: trailing whitespace or missing EOF newline."
|
||||
echo "We recommend using an IDE to prevent this from happening."
|
||||
exit 1
|
||||
fi
|
||||
4
.github/workflows/cla.yml
vendored
4
.github/workflows/cla.yml
vendored
@@ -5,7 +5,7 @@ on:
|
||||
pull_request_target:
|
||||
types: [opened,closed,synchronize]
|
||||
paths:
|
||||
- '**CP14**'
|
||||
- '**/*.cs' # Указываем, что триггер срабатывает только при изменении .cs файлов
|
||||
|
||||
# explicitly configure permissions, in case your GITHUB_TOKEN workflow permissions are set to read-only in repository settings
|
||||
permissions:
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: "CLA Assistant"
|
||||
if: ((github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target') && github.actor != 'TheShuEd'
|
||||
if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target'
|
||||
uses: contributor-assistant/github-action@v2.6.1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
2
.github/workflows/close-master-pr.yml
vendored
2
.github/workflows/close-master-pr.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
steps:
|
||||
- uses: superbrothers/close-pull-request@v3
|
||||
with:
|
||||
comment: "Thank you for your contribution! It appears you created a PR from your master branch, this is [something you should avoid doing](https://jmeridth.com/posts/do-not-issue-pull-requests-from-your-master-branch/), and thus this PR has been automatically closed. \n \n We suggest you follow [our git usage documentation](https://docs.spacestation14.com/en/general-development/setup/git-for-the-ss14-developer.html). \n \n You can move your current work from the master branch to another branch by following [these commands](https://ohshitgit.com/#accidental-commit-master). And then you may recreate your PR using the new branch."
|
||||
comment: "Thank you for contributing to the Space Station 14 repository. Unfortunately, it looks like you submitted your pull request from the master branch. We suggest you follow [our git usage documentation](https://docs.spacestation14.com/en/general-development/setup/git-for-the-ss14-developer.html) \n\n You can move your current work from the master branch to another branch by doing `git branch <branch_name` and resetting the master branch."
|
||||
|
||||
# If you prefer to just comment on the pr and not close it, uncomment the bellow and comment the above
|
||||
|
||||
|
||||
46
.github/workflows/publish-testing.yml
vendored
46
.github/workflows/publish-testing.yml
vendored
@@ -1,46 +0,0 @@
|
||||
name: Publish Testing
|
||||
|
||||
concurrency:
|
||||
group: publish-testing
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '0 10 * * *'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3.6.0
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
- name: Setup .NET Core
|
||||
uses: actions/setup-dotnet@v3.2.0
|
||||
with:
|
||||
dotnet-version: 9.0.x
|
||||
|
||||
- name: Get Engine Tag
|
||||
run: |
|
||||
cd RobustToolbox
|
||||
git fetch --depth=1
|
||||
|
||||
- name: Install dependencies
|
||||
run: dotnet restore
|
||||
|
||||
- name: Build Packaging
|
||||
run: dotnet build Content.Packaging --configuration Release --no-restore /m
|
||||
|
||||
- name: Package server
|
||||
run: dotnet run --project Content.Packaging server --platform win-x64 --platform linux-x64 --platform osx-x64 --platform linux-arm64
|
||||
|
||||
- name: Package client
|
||||
run: dotnet run --project Content.Packaging client --no-wipe-release
|
||||
|
||||
- name: Publish version
|
||||
run: Tools/publish_multi_request.py --fork-id wizards-testing
|
||||
env:
|
||||
PUBLISH_TOKEN: ${{ secrets.PUBLISH_TOKEN }}
|
||||
GITHUB_REPOSITORY: ${{ vars.GITHUB_REPOSITORY }}
|
||||
7
.github/workflows/publish.yml
vendored
7
.github/workflows/publish.yml
vendored
@@ -2,7 +2,6 @@ name: Publish
|
||||
|
||||
concurrency:
|
||||
group: publish
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
@@ -17,11 +16,11 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: sudo apt-get install -y python3-paramiko python3-lxml
|
||||
|
||||
- uses: actions/checkout@v4.2.2
|
||||
- uses: actions/checkout@v3.6.0
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
- name: Setup .NET Core
|
||||
uses: actions/setup-dotnet@v4.1.0
|
||||
uses: actions/setup-dotnet@v3.2.0
|
||||
with:
|
||||
dotnet-version: 9.0.x
|
||||
|
||||
@@ -49,14 +48,12 @@ jobs:
|
||||
GITHUB_REPOSITORY: ${{ vars.GITHUB_REPOSITORY }}
|
||||
|
||||
- name: Publish changelog (Discord)
|
||||
continue-on-error: true
|
||||
run: Tools/actions_changelogs_since_last_run.py
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
DISCORD_WEBHOOK_URL: ${{ secrets.CHANGELOG_DISCORD_WEBHOOK }}
|
||||
|
||||
- name: Publish changelog (RSS)
|
||||
continue-on-error: true
|
||||
run: Tools/actions_changelog_rss.py
|
||||
env:
|
||||
CHANGELOG_RSS_KEY: ${{ secrets.CHANGELOG_RSS_KEY }}
|
||||
|
||||
4
.github/workflows/rsi-diff.yml
vendored
4
.github/workflows/rsi-diff.yml
vendored
@@ -11,14 +11,14 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4.2.2
|
||||
uses: actions/checkout@v3.6.0
|
||||
|
||||
- name: Get changed files
|
||||
id: files
|
||||
uses: Ana06/get-changed-files@v2.3.0
|
||||
with:
|
||||
format: 'space-delimited'
|
||||
filter: |
|
||||
filter: |
|
||||
**.rsi
|
||||
**.png
|
||||
|
||||
|
||||
4
.github/workflows/test-packaging.yml
vendored
4
.github/workflows/test-packaging.yml
vendored
@@ -34,7 +34,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout Master
|
||||
uses: actions/checkout@v4.2.2
|
||||
uses: actions/checkout@v3.6.0
|
||||
|
||||
- name: Setup Submodule
|
||||
run: |
|
||||
@@ -49,7 +49,7 @@ jobs:
|
||||
git submodule update --init --recursive
|
||||
|
||||
- name: Setup .NET Core
|
||||
uses: actions/setup-dotnet@v4.1.0
|
||||
uses: actions/setup-dotnet@v3.2.0
|
||||
with:
|
||||
dotnet-version: 9.0.x
|
||||
|
||||
|
||||
20
.github/workflows/update-credits.yml
vendored
20
.github/workflows/update-credits.yml
vendored
@@ -4,19 +4,19 @@ on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: 0 0 * * 0
|
||||
|
||||
|
||||
jobs:
|
||||
get_credits:
|
||||
runs-on: ubuntu-latest
|
||||
# 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'
|
||||
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4.2.2
|
||||
- uses: actions/checkout@v3.6.0
|
||||
with:
|
||||
ref: master
|
||||
|
||||
|
||||
- name: Get this week's Contributors
|
||||
shell: pwsh
|
||||
env:
|
||||
@@ -25,25 +25,25 @@ jobs:
|
||||
|
||||
# TODO
|
||||
#- name: Get this week's Patreons
|
||||
# run: Tools/script2dumppatreons > Resources/Credits/Patrons.yml
|
||||
|
||||
# run: Tools/script2dumppatreons > Resources/Credits/Patrons.yml
|
||||
|
||||
# MAKE SURE YOU ENABLED "Allow GitHub Actions to create and approve pull requests" IN YOUR ACTIONS, OTHERWISE IT WILL MOST LIKELY FAIL
|
||||
|
||||
|
||||
# For this you can use a pat token of an account with direct push access to the repo if you have protected branches.
|
||||
# For this you can use a pat token of an account with direct push access to the repo if you have protected branches.
|
||||
# Uncomment this and comment the other line if you do this.
|
||||
# https://github.com/stefanzweifel/git-auto-commit-action#push-to-protected-branches
|
||||
|
||||
|
||||
#- name: Commit new credit files
|
||||
# uses: stefanzweifel/git-auto-commit-action@v4
|
||||
# with:
|
||||
# commit_message: Update Credits
|
||||
# commit_author: PJBot <pieterjan.briers+bot@gmail.com>
|
||||
|
||||
|
||||
# This will make a PR
|
||||
- name: Set current date as env variable
|
||||
run: echo "NOW=$(date +'%Y-%m-%dT%H-%M-%S')" >> $GITHUB_ENV
|
||||
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v5
|
||||
with:
|
||||
|
||||
2
.github/workflows/validate-rgas.yml
vendored
2
.github/workflows/validate-rgas.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
if: github.actor != 'PJBot' && github.event.pull_request.draft == false
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4.2.2
|
||||
- uses: actions/checkout@v3.6.0
|
||||
- name: Setup Submodule
|
||||
run: git submodule update --init
|
||||
- name: Pull engine updates
|
||||
|
||||
2
.github/workflows/validate-rsis.yml
vendored
2
.github/workflows/validate-rsis.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
||||
name: Validate RSIs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4.2.2
|
||||
- uses: actions/checkout@v3.6.0
|
||||
- name: Setup Submodule
|
||||
run: git submodule update --init
|
||||
- name: Pull engine updates
|
||||
|
||||
2
.github/workflows/validate_mapfiles.yml
vendored
2
.github/workflows/validate_mapfiles.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
if: github.actor != 'PJBot' && github.event.pull_request.draft == false
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4.2.2
|
||||
- uses: actions/checkout@v3.6.0
|
||||
- name: Setup Submodule
|
||||
run: git submodule update --init
|
||||
- name: Pull engine updates
|
||||
|
||||
4
.github/workflows/yaml-linter.yml
vendored
4
.github/workflows/yaml-linter.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
||||
if: github.actor != 'PJBot' && github.event.pull_request.draft == false
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4.2.2
|
||||
- uses: actions/checkout@v3.6.0
|
||||
- name: Setup submodule
|
||||
run: |
|
||||
git submodule update --init --recursive
|
||||
@@ -24,7 +24,7 @@ jobs:
|
||||
cd RobustToolbox/
|
||||
git submodule update --init --recursive
|
||||
- name: Setup .NET Core
|
||||
uses: actions/setup-dotnet@v4.1.0
|
||||
uses: actions/setup-dotnet@v3.2.0
|
||||
with:
|
||||
dotnet-version: 9.0.x
|
||||
- name: Install dependencies
|
||||
|
||||
44
.vscode/tasks.json
vendored
44
.vscode/tasks.json
vendored
@@ -32,50 +32,6 @@
|
||||
"/consoleloggerparameters:'ForceNoAlign;NoSummary'"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"label": "test",
|
||||
"command": "dotnet",
|
||||
"type": "shell",
|
||||
"args": [
|
||||
"test",
|
||||
"--no-build",
|
||||
"--configuration",
|
||||
"DebugOpt",
|
||||
"Content.Tests/Content.Tests.csproj",
|
||||
"--",
|
||||
"NUnit.ConsoleOut=0"
|
||||
],
|
||||
"group": {
|
||||
"kind": "test"
|
||||
},
|
||||
"presentation": {
|
||||
"reveal": "silent"
|
||||
},
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"label": "integration-test",
|
||||
"command": "dotnet",
|
||||
"type": "shell",
|
||||
"args": [
|
||||
"test",
|
||||
"--no-build",
|
||||
"--configuration",
|
||||
"DebugOpt",
|
||||
"Content.IntegrationTests/Content.IntegrationTests.csproj",
|
||||
"--",
|
||||
"NUnit.ConsoleOut=0",
|
||||
"NUnit.MapWarningTo=Failed.ConsoleOut=0",
|
||||
"NUnit.MapWarningTo=Failed"
|
||||
],
|
||||
"group": {
|
||||
"kind": "test"
|
||||
},
|
||||
"presentation": {
|
||||
"reveal": "silent"
|
||||
},
|
||||
"problemMatcher": "$msCompile"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -12,12 +12,12 @@ You want to handle the Build, Clean and Rebuild tasks to prevent missing task er
|
||||
If you want to learn more about these kinds of things, check out Microsoft's official documentation about MSBuild:
|
||||
https://docs.microsoft.com/en-us/visualstudio/msbuild/msbuild
|
||||
-->
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Python>python3</Python>
|
||||
<Python Condition="'$(OS)'=='Windows_NT' Or '$(OS)'=='Windows'">py -3</Python>
|
||||
<ProjectGuid>{C899FCA4-7037-4E49-ABC2-44DE72487110}</ProjectGuid>
|
||||
<TargetFramework>net4.7.2</TargetFramework>
|
||||
<TargetFrameworkMoniker>.NETFramework, Version=v4.7.2</TargetFrameworkMoniker>
|
||||
<RestorePackages>false</RestorePackages>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
|
||||
@@ -5,7 +5,6 @@ import subprocess
|
||||
import sys
|
||||
import os
|
||||
import shutil
|
||||
import time
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
@@ -105,21 +104,7 @@ def reset_solution():
|
||||
with SOLUTION_PATH.open("w") as f:
|
||||
f.write(content)
|
||||
|
||||
def check_for_zip_download():
|
||||
# Check if .git exists,
|
||||
cur_dir = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
|
||||
if not os.path.isdir(os.path.join(cur_dir, ".git")):
|
||||
print("It appears that you downloaded this repository directly from GitHub. (Using the .zip download option) \n"
|
||||
"When downloading straight from GitHub, it leaves out important information that git needs to function. "
|
||||
"Such as information to download the engine or even the ability to even be able to create contributions. \n"
|
||||
"Please read and follow https://docs.spacestation14.com/en/general-development/setup/setting-up-a-development-environment.html \n"
|
||||
"If you just want a Sandbox Server, you are following the wrong guide! You can download a premade server following the instructions here:"
|
||||
"https://docs.spacestation14.com/en/general-development/setup/server-hosting-tutorial.html \n"
|
||||
"Closing automatically in 30 seconds.")
|
||||
time.sleep(30)
|
||||
exit(1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
check_for_zip_download()
|
||||
install_hooks()
|
||||
update_submodules()
|
||||
|
||||
@@ -9,14 +9,13 @@ using Content.IntegrationTests.Pair;
|
||||
using Content.Shared.Clothing.Components;
|
||||
using Content.Shared.Doors.Components;
|
||||
using Content.Shared.Item;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared;
|
||||
using Robust.Shared.Analyzers;
|
||||
using Robust.Shared.EntitySerialization;
|
||||
using Robust.Shared.EntitySerialization.Systems;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Map.Components;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Benchmarks;
|
||||
|
||||
@@ -29,10 +28,11 @@ namespace Content.Benchmarks;
|
||||
[CategoriesColumn]
|
||||
public class ComponentQueryBenchmark
|
||||
{
|
||||
public const string Map = "Maps/saltern.yml";
|
||||
public const string Map = "Maps/atlas.yml";
|
||||
|
||||
private TestPair _pair = default!;
|
||||
private IEntityManager _entMan = default!;
|
||||
private MapId _mapId = new(10);
|
||||
private EntityQuery<ItemComponent> _itemQuery;
|
||||
private EntityQuery<ClothingComponent> _clothingQuery;
|
||||
private EntityQuery<MapComponent> _mapQuery;
|
||||
@@ -54,10 +54,10 @@ public class ComponentQueryBenchmark
|
||||
_pair.Server.ResolveDependency<IRobustRandom>().SetSeed(42);
|
||||
_pair.Server.WaitPost(() =>
|
||||
{
|
||||
var map = new ResPath(Map);
|
||||
var opts = DeserializationOptions.Default with {InitializeMaps = true};
|
||||
if (!_entMan.System<MapLoaderSystem>().TryLoadMap(map, out _, out _, opts))
|
||||
var success = _entMan.System<MapLoaderSystem>().TryLoad(_mapId, Map, out _);
|
||||
if (!success)
|
||||
throw new Exception("Map load failed");
|
||||
_pair.Server.MapMan.DoMapInitialize(_mapId);
|
||||
}).GetAwaiter().GetResult();
|
||||
|
||||
_items = new EntityUid[_entMan.Count<ItemComponent>()];
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace Content.Benchmarks
|
||||
for (var i = 0; i < Aabbs1.Length; i++)
|
||||
{
|
||||
var aabb = Aabbs1[i];
|
||||
_b2Tree.CreateProxy(aabb, uint.MaxValue, i);
|
||||
_b2Tree.CreateProxy(aabb, i);
|
||||
_tree.Add(i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,13 +6,12 @@ using BenchmarkDotNet.Attributes;
|
||||
using Content.IntegrationTests;
|
||||
using Content.IntegrationTests.Pair;
|
||||
using Content.Server.Maps;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared;
|
||||
using Robust.Shared.Analyzers;
|
||||
using Robust.Shared.EntitySerialization.Systems;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Benchmarks;
|
||||
|
||||
@@ -21,7 +20,7 @@ public class MapLoadBenchmark
|
||||
{
|
||||
private TestPair _pair = default!;
|
||||
private MapLoaderSystem _mapLoader = default!;
|
||||
private SharedMapSystem _mapSys = default!;
|
||||
private IMapManager _mapManager = default!;
|
||||
|
||||
[GlobalSetup]
|
||||
public void Setup()
|
||||
@@ -37,7 +36,7 @@ public class MapLoadBenchmark
|
||||
.ToDictionary(x => x.ID, x => x.MapPath.ToString());
|
||||
|
||||
_mapLoader = server.ResolveDependency<IEntitySystemManager>().GetEntitySystem<MapLoaderSystem>();
|
||||
_mapSys = server.ResolveDependency<IEntitySystemManager>().GetEntitySystem<SharedMapSystem>();
|
||||
_mapManager = server.ResolveDependency<IMapManager>();
|
||||
}
|
||||
|
||||
[GlobalCleanup]
|
||||
@@ -47,25 +46,23 @@ public class MapLoadBenchmark
|
||||
PoolManager.Shutdown();
|
||||
}
|
||||
|
||||
public static readonly string[] MapsSource = { "Empty", "Satlern", "Box", "Bagel", "Dev", "CentComm", "Core", "TestTeg", "Packed", "Omega", "Reach", "Meta", "Marathon", "MeteorArena", "Fland", "Oasis", "Convex"};
|
||||
public static readonly string[] MapsSource = { "Empty", "Satlern", "Box", "Bagel", "Dev", "CentComm", "Core", "TestTeg", "Packed", "Omega", "Reach", "Meta", "Marathon", "MeteorArena", "Fland", "Oasis", "Cog" };
|
||||
|
||||
[ParamsSource(nameof(MapsSource))]
|
||||
public string Map;
|
||||
|
||||
public Dictionary<string, string> Paths;
|
||||
private MapId _mapId;
|
||||
|
||||
[Benchmark]
|
||||
public async Task LoadMap()
|
||||
{
|
||||
var mapPath = new ResPath(Paths[Map]);
|
||||
var mapPath = Paths[Map];
|
||||
var server = _pair.Server;
|
||||
await server.WaitPost(() =>
|
||||
{
|
||||
var success = _mapLoader.TryLoadMap(mapPath, out var map, out _);
|
||||
var success = _mapLoader.TryLoad(new MapId(10), mapPath, out _);
|
||||
if (!success)
|
||||
throw new Exception("Map load failed");
|
||||
_mapId = map.Value.Comp.MapId;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -73,7 +70,9 @@ public class MapLoadBenchmark
|
||||
public void IterationCleanup()
|
||||
{
|
||||
var server = _pair.Server;
|
||||
server.WaitPost(() => _mapSys.DeleteMap(_mapId))
|
||||
.Wait();
|
||||
server.WaitPost(() =>
|
||||
{
|
||||
_mapManager.DeleteMap(new MapId(10));
|
||||
}).Wait();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,15 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using BenchmarkDotNet.Running;
|
||||
using Content.IntegrationTests;
|
||||
using Content.Server.Maps;
|
||||
#if DEBUG
|
||||
using BenchmarkDotNet.Configs;
|
||||
#else
|
||||
using Robust.Benchmarks.Configs;
|
||||
#endif
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Benchmarks
|
||||
{
|
||||
@@ -14,15 +22,11 @@ namespace Content.Benchmarks
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
Console.WriteLine("\nWARNING: YOU ARE RUNNING A DEBUG BUILD, USE A RELEASE BUILD FOR AN ACCURATE BENCHMARK");
|
||||
Console.WriteLine("THE DEBUG BUILD IS ONLY GOOD FOR FIXING A CRASHING BENCHMARK\n");
|
||||
var baseConfig = new DebugInProcessConfig();
|
||||
BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args, new DebugInProcessConfig());
|
||||
#else
|
||||
var baseConfig = Environment.GetEnvironmentVariable("ROBUST_BENCHMARKS_ENABLE_SQL") != null
|
||||
? DefaultSQLConfig.Instance
|
||||
: DefaultConfig.Instance;
|
||||
#endif
|
||||
var config = ManualConfig.Create(baseConfig);
|
||||
config.BuildTimeout = TimeSpan.FromMinutes(5);
|
||||
var config = Environment.GetEnvironmentVariable("ROBUST_BENCHMARKS_ENABLE_SQL") != null ? DefaultSQLConfig.Instance : null;
|
||||
BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args, config);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,16 +7,13 @@ using Content.IntegrationTests;
|
||||
using Content.IntegrationTests.Pair;
|
||||
using Content.Server.Mind;
|
||||
using Content.Server.Warps;
|
||||
using Content.Shared.Warps;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared;
|
||||
using Robust.Shared.Analyzers;
|
||||
using Robust.Shared.EntitySerialization;
|
||||
using Robust.Shared.EntitySerialization.Systems;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Benchmarks;
|
||||
|
||||
@@ -37,6 +34,7 @@ public class PvsBenchmark
|
||||
|
||||
private TestPair _pair = default!;
|
||||
private IEntityManager _entMan = default!;
|
||||
private MapId _mapId = new(10);
|
||||
private ICommonSession[] _players = default!;
|
||||
private EntityCoordinates[] _spawns = default!;
|
||||
public int _cycleOffset = 0;
|
||||
@@ -67,10 +65,10 @@ public class PvsBenchmark
|
||||
_pair.Server.ResolveDependency<IRobustRandom>().SetSeed(42);
|
||||
await _pair.Server.WaitPost(() =>
|
||||
{
|
||||
var path = new ResPath(Map);
|
||||
var opts = DeserializationOptions.Default with {InitializeMaps = true};
|
||||
if (!_entMan.System<MapLoaderSystem>().TryLoadMap(path, out _, out _, opts))
|
||||
var success = _entMan.System<MapLoaderSystem>().TryLoad(_mapId, Map, out _);
|
||||
if (!success)
|
||||
throw new Exception("Map load failed");
|
||||
_pair.Server.MapMan.DoMapInitialize(_mapId);
|
||||
});
|
||||
|
||||
// Get list of ghost warp positions
|
||||
|
||||
@@ -1,126 +0,0 @@
|
||||
#nullable enable
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading.Tasks;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Content.IntegrationTests;
|
||||
using Content.IntegrationTests.Pair;
|
||||
using Robust.Shared;
|
||||
using Robust.Shared.Analyzers;
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.Benchmarks;
|
||||
|
||||
[Virtual]
|
||||
public class RaiseEventBenchmark
|
||||
{
|
||||
private TestPair _pair = default!;
|
||||
private BenchSystem _sys = default!;
|
||||
|
||||
[GlobalSetup]
|
||||
public void Setup()
|
||||
{
|
||||
ProgramShared.PathOffset = "../../../../";
|
||||
PoolManager.Startup(typeof(BenchSystem).Assembly);
|
||||
_pair = PoolManager.GetServerClient().GetAwaiter().GetResult();
|
||||
var entMan = _pair.Server.EntMan;
|
||||
_sys = entMan.System<BenchSystem>();
|
||||
|
||||
_pair.Server.WaitPost(() =>
|
||||
{
|
||||
var uid = entMan.Spawn();
|
||||
_sys.Ent = new(uid, entMan.GetComponent<TransformComponent>(uid));
|
||||
_sys.Ent2 = new(_sys.Ent.Owner, _sys.Ent.Comp);
|
||||
})
|
||||
.GetAwaiter()
|
||||
.GetResult();
|
||||
}
|
||||
|
||||
[GlobalCleanup]
|
||||
public async Task Cleanup()
|
||||
{
|
||||
await _pair.DisposeAsync();
|
||||
PoolManager.Shutdown();
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = true)]
|
||||
public int RaiseEvent()
|
||||
{
|
||||
return _sys.RaiseEvent();
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public int RaiseCompEvent()
|
||||
{
|
||||
return _sys.RaiseCompEvent();
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public int RaiseICompEvent()
|
||||
{
|
||||
return _sys.RaiseICompEvent();
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public int RaiseCSharpEvent()
|
||||
{
|
||||
return _sys.CSharpEvent();
|
||||
}
|
||||
|
||||
public sealed class BenchSystem : EntitySystem
|
||||
{
|
||||
public Entity<TransformComponent> Ent;
|
||||
public Entity<IComponent> Ent2;
|
||||
|
||||
public delegate void EntityEventHandler(EntityUid uid, TransformComponent comp, ref BenchEv ev);
|
||||
|
||||
public event EntityEventHandler? OnCSharpEvent;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<TransformComponent, BenchEv>(OnEvent);
|
||||
OnCSharpEvent += OnEvent;
|
||||
}
|
||||
|
||||
public int RaiseEvent()
|
||||
{
|
||||
var ev = new BenchEv();
|
||||
RaiseLocalEvent(Ent.Owner, ref ev);
|
||||
return ev.N;
|
||||
}
|
||||
|
||||
public int RaiseCompEvent()
|
||||
{
|
||||
var ev = new BenchEv();
|
||||
EntityManager.EventBus.RaiseComponentEvent(Ent.Owner, Ent.Comp, ref ev);
|
||||
return ev.N;
|
||||
}
|
||||
|
||||
public int RaiseICompEvent()
|
||||
{
|
||||
// Raise with an IComponent instead of concrete type
|
||||
var ev = new BenchEv();
|
||||
EntityManager.EventBus.RaiseComponentEvent(Ent2.Owner, Ent2.Comp, ref ev);
|
||||
return ev.N;
|
||||
}
|
||||
|
||||
public int CSharpEvent()
|
||||
{
|
||||
var ev = new BenchEv();
|
||||
OnCSharpEvent?.Invoke(Ent.Owner, Ent.Comp, ref ev);
|
||||
return ev.N;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private void OnEvent(EntityUid uid, TransformComponent component, ref BenchEv args)
|
||||
{
|
||||
args.N += uid.Id;
|
||||
}
|
||||
|
||||
[ByRefEvent]
|
||||
public struct BenchEv
|
||||
{
|
||||
public int N;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,8 @@
|
||||
using Content.Shared.Access;
|
||||
using Content.Shared.Access.Components;
|
||||
using Content.Shared.Access.Systems;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared.Containers.ItemSlots;
|
||||
using Content.Shared.CrewManifest;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Prototypes;
|
||||
using static Content.Shared.Access.Components.IdCardConsoleComponent;
|
||||
|
||||
@@ -13,21 +11,13 @@ namespace Content.Client.Access.UI
|
||||
public sealed class IdCardConsoleBoundUserInterface : BoundUserInterface
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly IConfigurationManager _cfgManager = default!;
|
||||
private readonly SharedIdCardConsoleSystem _idCardConsoleSystem = default!;
|
||||
|
||||
private IdCardConsoleWindow? _window;
|
||||
|
||||
// CCVar.
|
||||
private int _maxNameLength;
|
||||
private int _maxIdJobLength;
|
||||
|
||||
public IdCardConsoleBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
|
||||
{
|
||||
_idCardConsoleSystem = EntMan.System<SharedIdCardConsoleSystem>();
|
||||
|
||||
_maxNameLength =_cfgManager.GetCVar(CCVars.MaxNameLength);
|
||||
_maxIdJobLength = _cfgManager.GetCVar(CCVars.MaxIdJobLength);
|
||||
}
|
||||
|
||||
protected override void Open()
|
||||
@@ -76,11 +66,11 @@ namespace Content.Client.Access.UI
|
||||
|
||||
public void SubmitData(string newFullName, string newJobTitle, List<ProtoId<AccessLevelPrototype>> newAccessList, string newJobPrototype)
|
||||
{
|
||||
if (newFullName.Length > _maxNameLength)
|
||||
newFullName = newFullName[.._maxNameLength];
|
||||
if (newFullName.Length > MaxFullNameLength)
|
||||
newFullName = newFullName[..MaxFullNameLength];
|
||||
|
||||
if (newJobTitle.Length > _maxIdJobLength)
|
||||
newJobTitle = newJobTitle[.._maxIdJobLength];
|
||||
if (newJobTitle.Length > MaxJobTitleLength)
|
||||
newJobTitle = newJobTitle[..MaxJobTitleLength];
|
||||
|
||||
SendMessage(new WriteToTargetIdMessage(
|
||||
newFullName,
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
using System.Linq;
|
||||
using Content.Shared.Access;
|
||||
using Content.Shared.Access.Systems;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared.Roles;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Prototypes;
|
||||
using static Content.Shared.Access.Components.IdCardConsoleComponent;
|
||||
|
||||
@@ -16,17 +14,12 @@ namespace Content.Client.Access.UI
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class IdCardConsoleWindow : DefaultWindow
|
||||
{
|
||||
[Dependency] private readonly IConfigurationManager _cfgManager = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly ILogManager _logManager = default!;
|
||||
private readonly ISawmill _logMill = default!;
|
||||
|
||||
private readonly IdCardConsoleBoundUserInterface _owner;
|
||||
|
||||
// CCVar.
|
||||
private int _maxNameLength;
|
||||
private int _maxIdJobLength;
|
||||
|
||||
private AccessLevelControl _accessButtons = new();
|
||||
private readonly List<string> _jobPrototypeIds = new();
|
||||
|
||||
@@ -46,11 +39,7 @@ namespace Content.Client.Access.UI
|
||||
|
||||
_owner = owner;
|
||||
|
||||
_maxNameLength = _cfgManager.GetCVar(CCVars.MaxNameLength);
|
||||
_maxIdJobLength = _cfgManager.GetCVar(CCVars.MaxIdJobLength);
|
||||
|
||||
FullNameLineEdit.OnTextEntered += _ => SubmitData();
|
||||
FullNameLineEdit.IsValid = s => s.Length <= _maxNameLength;
|
||||
FullNameLineEdit.OnTextChanged += _ =>
|
||||
{
|
||||
FullNameSaveButton.Disabled = FullNameSaveButton.Text == _lastFullName;
|
||||
@@ -58,7 +47,6 @@ namespace Content.Client.Access.UI
|
||||
FullNameSaveButton.OnPressed += _ => SubmitData();
|
||||
|
||||
JobTitleLineEdit.OnTextEntered += _ => SubmitData();
|
||||
JobTitleLineEdit.IsValid = s => s.Length <= _maxIdJobLength;
|
||||
JobTitleLineEdit.OnTextChanged += _ =>
|
||||
{
|
||||
JobTitleSaveButton.Disabled = JobTitleLineEdit.Text == _lastJobTitle;
|
||||
@@ -186,8 +174,7 @@ namespace Content.Client.Access.UI
|
||||
new List<ProtoId<AccessLevelPrototype>>());
|
||||
|
||||
var jobIndex = _jobPrototypeIds.IndexOf(state.TargetIdJobPrototype);
|
||||
// If the job index is < 0 that means they don't have a job registered in the station records
|
||||
// or the IdCardComponent's JobPrototype field.
|
||||
// If the job index is < 0 that means they don't have a job registered in the station records.
|
||||
// For example, a new ID from a box would have no job index.
|
||||
if (jobIndex < 0)
|
||||
{
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Content.Shared.Actions;
|
||||
using Content.Shared.Charges.Systems;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Shared.ContentPack;
|
||||
@@ -23,7 +22,6 @@ namespace Content.Client.Actions
|
||||
{
|
||||
public delegate void OnActionReplaced(EntityUid actionId);
|
||||
|
||||
[Dependency] private readonly SharedChargesSystem _sharedCharges = default!;
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly IResourceManager _resources = default!;
|
||||
[Dependency] private readonly ISerializationManager _serialization = default!;
|
||||
@@ -53,6 +51,29 @@ namespace Content.Client.Actions
|
||||
SubscribeLocalEvent<EntityWorldTargetActionComponent, ComponentHandleState>(OnEntityWorldTargetHandleState);
|
||||
}
|
||||
|
||||
public override void FrameUpdate(float frameTime)
|
||||
{
|
||||
base.FrameUpdate(frameTime);
|
||||
|
||||
var worldActionQuery = EntityQueryEnumerator<WorldTargetActionComponent>();
|
||||
while (worldActionQuery.MoveNext(out var uid, out var action))
|
||||
{
|
||||
UpdateAction(uid, action);
|
||||
}
|
||||
|
||||
var instantActionQuery = EntityQueryEnumerator<InstantActionComponent>();
|
||||
while (instantActionQuery.MoveNext(out var uid, out var action))
|
||||
{
|
||||
UpdateAction(uid, action);
|
||||
}
|
||||
|
||||
var entityActionQuery = EntityQueryEnumerator<EntityTargetActionComponent>();
|
||||
while (entityActionQuery.MoveNext(out var uid, out var action))
|
||||
{
|
||||
UpdateAction(uid, action);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnInstantHandleState(EntityUid uid, InstantActionComponent component, ref ComponentHandleState args)
|
||||
{
|
||||
if (args.Current is not InstantActionComponentState state)
|
||||
@@ -67,7 +88,6 @@ namespace Content.Client.Actions
|
||||
return;
|
||||
|
||||
component.Whitelist = state.Whitelist;
|
||||
component.Blacklist = state.Blacklist;
|
||||
component.CanTargetSelf = state.CanTargetSelf;
|
||||
BaseHandleState<EntityTargetActionComponent>(uid, component, state);
|
||||
}
|
||||
@@ -106,6 +126,9 @@ namespace Content.Client.Actions
|
||||
component.Toggled = state.Toggled;
|
||||
component.Cooldown = state.Cooldown;
|
||||
component.UseDelay = state.UseDelay;
|
||||
component.Charges = state.Charges;
|
||||
component.MaxCharges = state.MaxCharges;
|
||||
component.RenewCharges = state.RenewCharges;
|
||||
component.Container = EnsureEntity<T>(state.Container, uid);
|
||||
component.EntityIcon = EnsureEntity<T>(state.EntityIcon, uid);
|
||||
component.CheckCanInteract = state.CheckCanInteract;
|
||||
@@ -114,7 +137,6 @@ namespace Content.Client.Actions
|
||||
component.Priority = state.Priority;
|
||||
component.AttachedEntity = EnsureEntity<T>(state.AttachedEntity, uid);
|
||||
component.RaiseOnUser = state.RaiseOnUser;
|
||||
component.RaiseOnAction = state.RaiseOnAction;
|
||||
component.AutoPopulate = state.AutoPopulate;
|
||||
component.Temporary = state.Temporary;
|
||||
component.ItemIconStyle = state.ItemIconStyle;
|
||||
@@ -128,8 +150,7 @@ namespace Content.Client.Actions
|
||||
if (!ResolveActionData(actionId, ref action))
|
||||
return;
|
||||
|
||||
// TODO: Decouple this.
|
||||
action.IconColor = _sharedCharges.GetCurrentCharges(actionId.Value) == 0 ? action.DisabledIconColor : action.OriginalIconColor;
|
||||
action.IconColor = action.Charges < 1 ? action.DisabledIconColor : action.OriginalIconColor;
|
||||
|
||||
base.UpdateAction(actionId, action);
|
||||
if (_playerManager.LocalEntity != action.AttachedEntity)
|
||||
@@ -202,7 +223,6 @@ namespace Content.Client.Actions
|
||||
return;
|
||||
|
||||
OnActionAdded?.Invoke(actionId);
|
||||
ActionsUpdated?.Invoke();
|
||||
}
|
||||
|
||||
protected override void ActionRemoved(EntityUid performer, EntityUid actionId, ActionsComponent comp, BaseActionComponent action)
|
||||
@@ -211,7 +231,6 @@ namespace Content.Client.Actions
|
||||
return;
|
||||
|
||||
OnActionRemoved?.Invoke(actionId);
|
||||
ActionsUpdated?.Invoke();
|
||||
}
|
||||
|
||||
public IEnumerable<(EntityUid Id, BaseActionComponent Comp)> GetClientActions()
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Content.Client.Administration.Systems;
|
||||
using Content.Client.Stylesheets;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared.Ghost;
|
||||
using Content.Shared.Mind;
|
||||
using Content.Shared.Roles;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.ResourceManagement;
|
||||
using Robust.Client.UserInterface;
|
||||
@@ -18,74 +14,32 @@ namespace Content.Client.Administration;
|
||||
|
||||
internal sealed class AdminNameOverlay : Overlay
|
||||
{
|
||||
[Dependency] private readonly IConfigurationManager _config = default!;
|
||||
|
||||
private readonly AdminSystem _system;
|
||||
private readonly IEntityManager _entityManager;
|
||||
private readonly IEyeManager _eyeManager;
|
||||
private readonly EntityLookupSystem _entityLookup;
|
||||
private readonly IUserInterfaceManager _userInterfaceManager;
|
||||
private readonly SharedRoleSystem _roles;
|
||||
private readonly Font _font;
|
||||
private readonly Font _fontBold;
|
||||
private AdminOverlayAntagFormat _overlayFormat;
|
||||
private AdminOverlayAntagSymbolStyle _overlaySymbolStyle;
|
||||
private bool _overlayPlaytime;
|
||||
private bool _overlayStartingJob;
|
||||
private float _ghostFadeDistance;
|
||||
private float _ghostHideDistance;
|
||||
private int _overlayStackMax;
|
||||
private float _overlayMergeDistance;
|
||||
|
||||
//TODO make this adjustable via GUI?
|
||||
//TODO make this adjustable via GUI
|
||||
private readonly ProtoId<RoleTypePrototype>[] _filter =
|
||||
["SoloAntagonist", "TeamAntagonist", "SiliconAntagonist", "FreeAgent"];
|
||||
|
||||
private readonly string _antagLabelClassic = Loc.GetString("admin-overlay-antag-classic");
|
||||
private readonly Color _antagColorClassic = Color.OrangeRed;
|
||||
|
||||
public AdminNameOverlay(
|
||||
AdminSystem system,
|
||||
IEntityManager entityManager,
|
||||
IEyeManager eyeManager,
|
||||
IResourceCache resourceCache,
|
||||
EntityLookupSystem entityLookup,
|
||||
IUserInterfaceManager userInterfaceManager,
|
||||
IConfigurationManager config,
|
||||
SharedRoleSystem roles)
|
||||
public AdminNameOverlay(AdminSystem system, IEntityManager entityManager, IEyeManager eyeManager, IResourceCache resourceCache, EntityLookupSystem entityLookup, IUserInterfaceManager userInterfaceManager)
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
|
||||
_system = system;
|
||||
_entityManager = entityManager;
|
||||
_eyeManager = eyeManager;
|
||||
_entityLookup = entityLookup;
|
||||
_userInterfaceManager = userInterfaceManager;
|
||||
_roles = roles;
|
||||
ZIndex = 200;
|
||||
// Setting these to a specific ttf would break the antag symbols
|
||||
_font = resourceCache.NotoStack();
|
||||
_fontBold = resourceCache.NotoStack(variation: "Bold");
|
||||
|
||||
config.OnValueChanged(CCVars.AdminOverlayAntagFormat, (show) => { _overlayFormat = UpdateOverlayFormat(show); }, true);
|
||||
config.OnValueChanged(CCVars.AdminOverlaySymbolStyle, (show) => { _overlaySymbolStyle = UpdateOverlaySymbolStyle(show); }, true);
|
||||
config.OnValueChanged(CCVars.AdminOverlayPlaytime, (show) => { _overlayPlaytime = show; }, true);
|
||||
config.OnValueChanged(CCVars.AdminOverlayStartingJob, (show) => { _overlayStartingJob = show; }, true);
|
||||
config.OnValueChanged(CCVars.AdminOverlayGhostHideDistance, (f) => { _ghostHideDistance = f; }, true);
|
||||
config.OnValueChanged(CCVars.AdminOverlayGhostFadeDistance, (f) => { _ghostFadeDistance = f; }, true);
|
||||
config.OnValueChanged(CCVars.AdminOverlayStackMax, (i) => { _overlayStackMax = i; }, true);
|
||||
config.OnValueChanged(CCVars.AdminOverlayMergeDistance, (f) => { _overlayMergeDistance = f; }, true);
|
||||
}
|
||||
|
||||
private AdminOverlayAntagFormat UpdateOverlayFormat(string formatString)
|
||||
{
|
||||
if (!Enum.TryParse<AdminOverlayAntagFormat>(formatString, out var format))
|
||||
format = AdminOverlayAntagFormat.Binary;
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
private AdminOverlayAntagSymbolStyle UpdateOverlaySymbolStyle(string symbolString)
|
||||
{
|
||||
if (!Enum.TryParse<AdminOverlayAntagSymbolStyle>(symbolString, out var symbolStyle))
|
||||
symbolStyle = AdminOverlayAntagSymbolStyle.Off;
|
||||
|
||||
return symbolStyle;
|
||||
_font = new VectorFont(resourceCache.GetResource<FontResource>("/Fonts/NotoSans/NotoSans-Regular.ttf"), 10);
|
||||
}
|
||||
|
||||
public override OverlaySpace Space => OverlaySpace.ScreenSpace;
|
||||
@@ -93,169 +47,54 @@ internal sealed class AdminNameOverlay : Overlay
|
||||
protected override void Draw(in OverlayDrawArgs args)
|
||||
{
|
||||
var viewport = args.WorldAABB;
|
||||
var colorDisconnected = Color.White;
|
||||
var uiScale = _userInterfaceManager.RootControl.UIScale;
|
||||
var lineoffset = new Vector2(0f, 14f) * uiScale;
|
||||
var drawnOverlays = new List<(Vector2,Vector2)>() ; // A saved list of the overlays already drawn
|
||||
|
||||
// Get all player positions before drawing overlays, so they can be sorted before iteration
|
||||
var sortable = new List<(PlayerInfo, Box2, EntityUid, Vector2)>();
|
||||
foreach (var info in _system.PlayerList)
|
||||
//TODO make this adjustable via GUI
|
||||
var classic = _config.GetCVar(CCVars.AdminOverlayClassic);
|
||||
|
||||
foreach (var playerInfo in _system.PlayerList)
|
||||
{
|
||||
var entity = _entityManager.GetEntity(info.NetEntity);
|
||||
var entity = _entityManager.GetEntity(playerInfo.NetEntity);
|
||||
|
||||
// If entity does not exist or is on a different map, skip
|
||||
if (entity == null
|
||||
|| !_entityManager.EntityExists(entity)
|
||||
|| _entityManager.GetComponent<TransformComponent>(entity.Value).MapID != args.MapId)
|
||||
// Otherwise the entity can not exist yet
|
||||
if (entity == null || !_entityManager.EntityExists(entity))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// if not on the same map, continue
|
||||
if (_entityManager.GetComponent<TransformComponent>(entity.Value).MapID != args.MapId)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var aabb = _entityLookup.GetWorldAABB(entity.Value);
|
||||
// if not on screen, skip
|
||||
|
||||
// if not on screen, continue
|
||||
if (!aabb.Intersects(in viewport))
|
||||
{
|
||||
continue;
|
||||
|
||||
// Get on-screen coordinates of player
|
||||
var screenCoordinates = _eyeManager.WorldToScreen(aabb.Center).Rounded();
|
||||
|
||||
sortable.Add((info, aabb, entity.Value, screenCoordinates));
|
||||
}
|
||||
|
||||
// Draw overlays for visible players, starting from the top of the screen
|
||||
foreach (var info in sortable.OrderBy(s => s.Item4.Y).ToList())
|
||||
{
|
||||
var playerInfo = info.Item1;
|
||||
var aabb = info.Item2;
|
||||
var entity = info.Item3;
|
||||
var screenCoordinatesCenter = info.Item4;
|
||||
//the center position is kept separately, for simpler position comparison later
|
||||
var centerOffset = new Vector2(28f, -18f) * uiScale;
|
||||
var screenCoordinates = screenCoordinatesCenter + centerOffset;
|
||||
var alpha = 1f;
|
||||
|
||||
//TODO make a smarter system where the starting offset can be modified by the predicted position and size of already-drawn overlays/stacks?
|
||||
var currentOffset = Vector2.Zero;
|
||||
|
||||
// Ghosts near the cursor are made transparent/invisible
|
||||
// TODO would be "cheaper" if playerinfo already contained a ghost bool, this gets called every frame for every onscreen player!
|
||||
if (_entityManager.HasComponent<GhostComponent>(entity))
|
||||
{
|
||||
// We want the map positions here, so we don't have to worry about resolution and such shenanigans
|
||||
var mobPosition = aabb.Center;
|
||||
var mousePosition = _eyeManager
|
||||
.ScreenToMap(_userInterfaceManager.MousePositionScaled.Position * uiScale)
|
||||
.Position;
|
||||
var dist = Vector2.Distance(mobPosition, mousePosition);
|
||||
if (dist < _ghostHideDistance)
|
||||
continue;
|
||||
|
||||
alpha = Math.Clamp((dist - _ghostHideDistance) / (_ghostFadeDistance - _ghostHideDistance), 0f, 1f);
|
||||
colorDisconnected.A = alpha;
|
||||
}
|
||||
|
||||
// If the new overlay text block is within merge distance of any previous ones
|
||||
// merge them into a stack so they don't hide each other
|
||||
var stack = drawnOverlays.FindAll(x =>
|
||||
Vector2.Distance(_eyeManager.ScreenToMap(x.Item1).Position, aabb.Center) <= _overlayMergeDistance);
|
||||
if (stack.Count > 0)
|
||||
{
|
||||
screenCoordinates = stack.First().Item1 + centerOffset;
|
||||
// Replacing this overlay's coordinates for the later save with the stack root's coordinates
|
||||
// so that other overlays don't try to stack to these coordinates
|
||||
screenCoordinatesCenter = stack.First().Item1;
|
||||
var uiScale = _userInterfaceManager.RootControl.UIScale;
|
||||
var lineoffset = new Vector2(0f, 11f) * uiScale;
|
||||
var screenCoordinates = _eyeManager.WorldToScreen(aabb.Center +
|
||||
new Angle(-_eyeManager.CurrentEye.Rotation).RotateVec(
|
||||
aabb.TopRight - aabb.Center)) + new Vector2(1f, 7f);
|
||||
|
||||
var i = 1;
|
||||
foreach (var s in stack)
|
||||
{
|
||||
// additional entries after maximum stack size is reached will be drawn over the last entry
|
||||
if (i <= _overlayStackMax - 1)
|
||||
currentOffset = lineoffset + s.Item2 ;
|
||||
i++;
|
||||
}
|
||||
if (classic && playerInfo.Antag)
|
||||
{
|
||||
args.ScreenHandle.DrawString(_font, screenCoordinates + (lineoffset * 2), _antagLabelClassic, uiScale, _antagColorClassic);
|
||||
}
|
||||
else if (!classic && _filter.Contains(playerInfo.RoleProto.ID))
|
||||
{
|
||||
var label = Loc.GetString(playerInfo.RoleProto.Name).ToUpper();
|
||||
var color = playerInfo.RoleProto.Color;
|
||||
|
||||
args.ScreenHandle.DrawString(_font, screenCoordinates + (lineoffset * 2), label, uiScale, color);
|
||||
}
|
||||
|
||||
// Character name
|
||||
var color = Color.Aquamarine;
|
||||
color.A = alpha;
|
||||
args.ScreenHandle.DrawString(_font, screenCoordinates + currentOffset, playerInfo.CharacterName, uiScale, playerInfo.Connected ? color : colorDisconnected);
|
||||
currentOffset += lineoffset;
|
||||
|
||||
// Username
|
||||
color = Color.Yellow;
|
||||
color.A = alpha;
|
||||
args.ScreenHandle.DrawString(_font, screenCoordinates + currentOffset, playerInfo.Username, uiScale, playerInfo.Connected ? color : colorDisconnected);
|
||||
currentOffset += lineoffset;
|
||||
|
||||
// Playtime
|
||||
if (!string.IsNullOrEmpty(playerInfo.PlaytimeString) && _overlayPlaytime)
|
||||
{
|
||||
color = Color.Orange;
|
||||
color.A = alpha;
|
||||
args.ScreenHandle.DrawString(_font, screenCoordinates + currentOffset, playerInfo.PlaytimeString, uiScale, playerInfo.Connected ? color : colorDisconnected);
|
||||
currentOffset += lineoffset;
|
||||
}
|
||||
|
||||
// Job
|
||||
if (!string.IsNullOrEmpty(playerInfo.StartingJob) && _overlayStartingJob)
|
||||
{
|
||||
color = Color.GreenYellow;
|
||||
color.A = alpha;
|
||||
args.ScreenHandle.DrawString(_font, screenCoordinates + currentOffset, Loc.GetString(playerInfo.StartingJob), uiScale, playerInfo.Connected ? color : colorDisconnected);
|
||||
currentOffset += lineoffset;
|
||||
}
|
||||
|
||||
// Determine antag symbol
|
||||
string? symbol;
|
||||
switch (_overlaySymbolStyle)
|
||||
{
|
||||
case AdminOverlayAntagSymbolStyle.Specific:
|
||||
symbol = playerInfo.RoleProto.Symbol;
|
||||
break;
|
||||
case AdminOverlayAntagSymbolStyle.Basic:
|
||||
symbol = Loc.GetString("player-tab-antag-prefix");
|
||||
break;
|
||||
default:
|
||||
case AdminOverlayAntagSymbolStyle.Off:
|
||||
symbol = string.Empty;
|
||||
break;
|
||||
}
|
||||
|
||||
// Determine antag/role type name
|
||||
string? text;
|
||||
switch (_overlayFormat)
|
||||
{
|
||||
case AdminOverlayAntagFormat.Roletype:
|
||||
color = playerInfo.RoleProto.Color;
|
||||
symbol = _filter.Contains(playerInfo.RoleProto) ? symbol : string.Empty;
|
||||
text = _filter.Contains(playerInfo.RoleProto)
|
||||
? Loc.GetString(playerInfo.RoleProto.Name).ToUpper()
|
||||
: string.Empty;
|
||||
break;
|
||||
case AdminOverlayAntagFormat.Subtype:
|
||||
color = playerInfo.RoleProto.Color;
|
||||
symbol = _filter.Contains(playerInfo.RoleProto) ? symbol : string.Empty;
|
||||
text = _filter.Contains(playerInfo.RoleProto)
|
||||
? _roles.GetRoleSubtypeLabel(playerInfo.RoleProto.Name, playerInfo.Subtype).ToUpper()
|
||||
: string.Empty;
|
||||
break;
|
||||
default:
|
||||
case AdminOverlayAntagFormat.Binary:
|
||||
color = Color.OrangeRed;
|
||||
symbol = playerInfo.Antag ? symbol : string.Empty;
|
||||
text = playerInfo.Antag ? _antagLabelClassic : string.Empty;
|
||||
break;
|
||||
}
|
||||
|
||||
// Draw antag label
|
||||
color.A = alpha;
|
||||
var label = !string.IsNullOrEmpty(symbol)
|
||||
? Loc.GetString("player-tab-character-name-antag-symbol", ("symbol", symbol), ("name", text))
|
||||
: text;
|
||||
args.ScreenHandle.DrawString(_fontBold, screenCoordinates + currentOffset, label, uiScale, color);
|
||||
currentOffset += lineoffset;
|
||||
|
||||
//Save the coordinates and size of the text block, for stack merge check
|
||||
drawnOverlays.Add((screenCoordinatesCenter, currentOffset));
|
||||
args.ScreenHandle.DrawString(_font, screenCoordinates + lineoffset, playerInfo.Username, uiScale, playerInfo.Connected ? Color.Yellow : Color.White);
|
||||
args.ScreenHandle.DrawString(_font, screenCoordinates, playerInfo.CharacterName, uiScale, playerInfo.Connected ? Color.Aquamarine : Color.White);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
namespace Content.Client.Administration;
|
||||
|
||||
public enum AdminOverlayAntagFormat
|
||||
{
|
||||
Binary,
|
||||
Roletype,
|
||||
Subtype
|
||||
}
|
||||
|
||||
public enum AdminOverlayAntagSymbolStyle
|
||||
{
|
||||
Off,
|
||||
Basic,
|
||||
Specific
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using Content.Client.Administration.Managers;
|
||||
using Content.Shared.Roles;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.ResourceManagement;
|
||||
using Robust.Client.UserInterface;
|
||||
@@ -15,8 +14,6 @@ namespace Content.Client.Administration.Systems
|
||||
[Dependency] private readonly IEyeManager _eyeManager = default!;
|
||||
[Dependency] private readonly EntityLookupSystem _entityLookup = default!;
|
||||
[Dependency] private readonly IUserInterfaceManager _userInterfaceManager = default!;
|
||||
[Dependency] private readonly IConfigurationManager _configurationManager = default!;
|
||||
[Dependency] private readonly SharedRoleSystem _roles = default!;
|
||||
|
||||
private AdminNameOverlay _adminNameOverlay = default!;
|
||||
|
||||
@@ -25,15 +22,7 @@ namespace Content.Client.Administration.Systems
|
||||
|
||||
private void InitializeOverlay()
|
||||
{
|
||||
_adminNameOverlay = new AdminNameOverlay(
|
||||
this,
|
||||
EntityManager,
|
||||
_eyeManager,
|
||||
_resourceCache,
|
||||
_entityLookup,
|
||||
_userInterfaceManager,
|
||||
_configurationManager,
|
||||
_roles);
|
||||
_adminNameOverlay = new AdminNameOverlay(this, EntityManager, _eyeManager, _resourceCache, _entityLookup, _userInterfaceManager);
|
||||
_adminManager.AdminStatusUpdated += OnAdminStatusUpdated;
|
||||
}
|
||||
|
||||
@@ -49,8 +38,7 @@ namespace Content.Client.Administration.Systems
|
||||
|
||||
public void AdminOverlayOn()
|
||||
{
|
||||
if (_overlayManager.HasOverlay<AdminNameOverlay>())
|
||||
return;
|
||||
if (_overlayManager.HasOverlay<AdminNameOverlay>()) return;
|
||||
_overlayManager.AddOverlay(_adminNameOverlay);
|
||||
OverlayEnabled?.Invoke();
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace Content.Client.Administration.Systems
|
||||
var verb = new VvVerb()
|
||||
{
|
||||
Text = Loc.GetString("view-variables"),
|
||||
Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/vv.svg.192dpi.png")),
|
||||
Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/vv.svg.192dpi.png")),
|
||||
Act = () => _clientConsoleHost.ExecuteCommand($"vv {GetNetEntity(args.Target)}"),
|
||||
ClientExclusive = true // opening VV window is client-side. Don't ask server to run this verb.
|
||||
};
|
||||
|
||||
@@ -19,11 +19,11 @@ namespace Content.Client.Administration.Systems
|
||||
OnBwoinkTextMessageRecieved?.Invoke(this, message);
|
||||
}
|
||||
|
||||
public void Send(NetUserId channelId, string text, bool playSound, bool adminOnly)
|
||||
public void Send(NetUserId channelId, string text, bool playSound)
|
||||
{
|
||||
// Reuse the channel ID as the 'true sender'.
|
||||
// Server will ignore this and if someone makes it not ignore this (which is bad, allows impersonation!!!), that will help.
|
||||
RaiseNetworkEvent(new BwoinkTextMessage(channelId, channelId, text, playSound: playSound, adminOnly: adminOnly));
|
||||
RaiseNetworkEvent(new BwoinkTextMessage(channelId, channelId, text, playSound: playSound));
|
||||
SendInputTextUpdated(channelId, false);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,8 +7,6 @@ namespace Content.Client.Administration.Systems;
|
||||
|
||||
public sealed class KillSignSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SpriteSystem _sprite = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<KillSignComponent, ComponentStartup>(KillSignAdded);
|
||||
@@ -20,10 +18,10 @@ public sealed class KillSignSystem : EntitySystem
|
||||
if (!TryComp<SpriteComponent>(uid, out var sprite))
|
||||
return;
|
||||
|
||||
if (!_sprite.LayerMapTryGet((uid, sprite), KillSignKey.Key, out var layer, false))
|
||||
if (!sprite.LayerMapTryGet(KillSignKey.Key, out var layer))
|
||||
return;
|
||||
|
||||
_sprite.RemoveLayer((uid, sprite), layer);
|
||||
sprite.RemoveLayer(layer);
|
||||
}
|
||||
|
||||
private void KillSignAdded(EntityUid uid, KillSignComponent component, ComponentStartup args)
|
||||
@@ -31,15 +29,15 @@ public sealed class KillSignSystem : EntitySystem
|
||||
if (!TryComp<SpriteComponent>(uid, out var sprite))
|
||||
return;
|
||||
|
||||
if (_sprite.LayerMapTryGet((uid, sprite), KillSignKey.Key, out var _, false))
|
||||
if (sprite.LayerMapTryGet(KillSignKey.Key, out var _))
|
||||
return;
|
||||
|
||||
var adj = _sprite.GetLocalBounds((uid, sprite)).Height / 2 + ((1.0f / 32) * 6.0f);
|
||||
var adj = sprite.Bounds.Height / 2 + ((1.0f/32) * 6.0f);
|
||||
|
||||
var layer = _sprite.AddLayer((uid, sprite), new SpriteSpecifier.Rsi(new ResPath("Objects/Misc/killsign.rsi"), "sign"));
|
||||
_sprite.LayerMapSet((uid, sprite), KillSignKey.Key, layer);
|
||||
var layer = sprite.AddLayer(new SpriteSpecifier.Rsi(new ResPath("Objects/Misc/killsign.rsi"), "sign"));
|
||||
sprite.LayerMapSet(KillSignKey.Key, layer);
|
||||
|
||||
_sprite.LayerSetOffset((uid, sprite), layer, new Vector2(0.0f, adj));
|
||||
sprite.LayerSetOffset(layer, new Vector2(0.0f, adj));
|
||||
sprite.LayerSetShader(layer, "unshaded");
|
||||
}
|
||||
|
||||
|
||||
59
Content.Client/Administration/UI/AdminUIHelpers.cs
Normal file
59
Content.Client/Administration/UI/AdminUIHelpers.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
using System.Threading;
|
||||
using Content.Client.Stylesheets;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Timer = Robust.Shared.Timing.Timer;
|
||||
|
||||
namespace Content.Client.Administration.UI;
|
||||
|
||||
public static class AdminUIHelpers
|
||||
{
|
||||
private static void ResetButton(Button button, ConfirmationData data)
|
||||
{
|
||||
data.Cancellation.Cancel();
|
||||
button.ModulateSelfOverride = null;
|
||||
button.Text = data.OriginalText;
|
||||
}
|
||||
|
||||
public static bool RemoveConfirm(Button button, Dictionary<Button, ConfirmationData> confirmations)
|
||||
{
|
||||
if (confirmations.Remove(button, out var data))
|
||||
{
|
||||
ResetButton(button, data);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void RemoveAllConfirms(Dictionary<Button, ConfirmationData> confirmations)
|
||||
{
|
||||
foreach (var (button, confirmation) in confirmations)
|
||||
{
|
||||
ResetButton(button, confirmation);
|
||||
}
|
||||
|
||||
confirmations.Clear();
|
||||
}
|
||||
|
||||
public static bool TryConfirm(Button button, Dictionary<Button, ConfirmationData> confirmations)
|
||||
{
|
||||
if (RemoveConfirm(button, confirmations))
|
||||
return true;
|
||||
|
||||
var data = new ConfirmationData(new CancellationTokenSource(), button.Text);
|
||||
confirmations[button] = data;
|
||||
|
||||
Timer.Spawn(TimeSpan.FromSeconds(5), () =>
|
||||
{
|
||||
confirmations.Remove(button);
|
||||
button.ModulateSelfOverride = null;
|
||||
button.Text = data.OriginalText;
|
||||
}, data.Cancellation.Token);
|
||||
|
||||
button.ModulateSelfOverride = StyleNano.ButtonColorCautionDefault;
|
||||
button.Text = Loc.GetString("admin-player-actions-confirm");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public readonly record struct ConfirmationData(CancellationTokenSource Cancellation, string? OriginalText);
|
||||
@@ -1,28 +1,23 @@
|
||||
<Control
|
||||
xmlns="https://spacestation14.io"
|
||||
xmlns:cc="clr-namespace:Content.Client.Administration.UI.CustomControls"
|
||||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls">
|
||||
xmlns:cc="clr-namespace:Content.Client.Administration.UI.CustomControls">
|
||||
<PanelContainer StyleClasses="BackgroundDark">
|
||||
<SplitContainer Orientation="Vertical" ResizeMode="NotResizable">
|
||||
<SplitContainer Orientation="Horizontal" VerticalExpand="True">
|
||||
<cc:PlayerListControl Access="Public" Name="ChannelSelector" HorizontalExpand="True" SizeFlagsStretchRatio="2" />
|
||||
<BoxContainer Orientation="Vertical" HorizontalExpand="True" SizeFlagsStretchRatio="2">
|
||||
<BoxContainer Access="Public" Name="BwoinkArea" VerticalExpand="True" />
|
||||
<SplitContainer Orientation="Horizontal" VerticalExpand="True">
|
||||
<cc:PlayerListControl Access="Public" Name="ChannelSelector" HorizontalExpand="True" SizeFlagsStretchRatio="1" />
|
||||
<BoxContainer Orientation="Vertical" HorizontalExpand="True" SizeFlagsStretchRatio="2">
|
||||
<BoxContainer Access="Public" Name="BwoinkArea" VerticalExpand="True" />
|
||||
<BoxContainer Orientation="Horizontal" HorizontalExpand="True">
|
||||
<CheckBox Visible="True" Name="PlaySound" Access="Public" Text="{Loc 'admin-bwoink-play-sound'}" Pressed="True" />
|
||||
<Control HorizontalExpand="True" MinWidth="5" />
|
||||
<Button Visible="True" Name="PopOut" Access="Public" Text="{Loc 'admin-logs-pop-out'}" StyleClasses="OpenBoth" HorizontalAlignment="Left" />
|
||||
<Control HorizontalExpand="True" />
|
||||
<Button Visible="False" Name="Bans" Text="{Loc 'admin-player-actions-bans'}" StyleClasses="OpenRight" />
|
||||
<Button Visible="False" Name="Notes" Text="{Loc 'admin-player-actions-notes'}" StyleClasses="OpenBoth" />
|
||||
<Button Visible="False" Name="Kick" Text="{Loc 'admin-player-actions-kick'}" StyleClasses="OpenBoth" />
|
||||
<Button Visible="False" Name="Ban" Text="{Loc 'admin-player-actions-ban'}" StyleClasses="OpenBoth" />
|
||||
<Button Visible="False" Name="Respawn" Text="{Loc 'admin-player-actions-respawn'}" StyleClasses="OpenBoth" />
|
||||
<Button Visible="False" Name="Follow" Text="{Loc 'admin-player-actions-follow'}" StyleClasses="OpenLeft" />
|
||||
</BoxContainer>
|
||||
</SplitContainer>
|
||||
<BoxContainer Orientation="Horizontal" SetHeight="30" >
|
||||
<CheckBox Name="AdminOnly" Access="Public" Text="{Loc 'admin-ahelp-admin-only'}" ToolTip="{Loc 'admin-ahelp-admin-only-tooltip'}" />
|
||||
<Control HorizontalExpand="True" MinWidth="5" />
|
||||
<CheckBox Name="PlaySound" Access="Public" Text="{Loc 'admin-bwoink-play-sound'}" Pressed="True" />
|
||||
<Control HorizontalExpand="True" MinWidth="5" />
|
||||
<Button Visible="True" Name="PopOut" Access="Public" Text="{Loc 'admin-logs-pop-out'}" StyleClasses="OpenBoth" HorizontalAlignment="Left" />
|
||||
<Control HorizontalExpand="True" />
|
||||
<Button Visible="False" Name="Bans" Text="{Loc 'admin-player-actions-bans'}" StyleClasses="OpenRight" />
|
||||
<Button Visible="False" Name="Notes" Text="{Loc 'admin-player-actions-notes'}" StyleClasses="OpenBoth" />
|
||||
<controls:ConfirmButton Visible="False" Name="Kick" Text="{Loc 'admin-player-actions-kick'}" ConfirmationText="{Loc 'admin-player-actions-confirm'}" StyleClasses="OpenBoth" />
|
||||
<Button Visible="False" Name="Ban" Text="{Loc 'admin-player-actions-ban'}" StyleClasses="OpenBoth" />
|
||||
<controls:ConfirmButton Visible="False" Name="Respawn" Text="{Loc 'admin-player-actions-respawn'}" ConfirmationText="{Loc 'admin-player-actions-confirm'}" StyleClasses="OpenBoth" />
|
||||
<Button Visible="False" Name="Follow" Text="{Loc 'admin-player-actions-follow'}" StyleClasses="OpenLeft" />
|
||||
</BoxContainer>
|
||||
</SplitContainer>
|
||||
</PanelContainer>
|
||||
|
||||
@@ -29,15 +29,13 @@ namespace Content.Client.Administration.UI.Bwoink
|
||||
public AdminAHelpUIHandler AHelpHelper = default!;
|
||||
|
||||
private PlayerInfo? _currentPlayer;
|
||||
private readonly Dictionary<Button, ConfirmationData> _confirmations = new();
|
||||
|
||||
public BwoinkControl()
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
IoCManager.InjectDependencies(this);
|
||||
|
||||
var newPlayerThreshold = 0;
|
||||
_cfg.OnValueChanged(CCVars.NewPlayerThreshold, (val) => { newPlayerThreshold = val; }, true);
|
||||
|
||||
var uiController = _ui.GetUIController<AHelpUIController>();
|
||||
if (uiController.UIHelper is not AdminAHelpUIHandler helper)
|
||||
return;
|
||||
@@ -47,8 +45,6 @@ namespace Content.Client.Administration.UI.Bwoink
|
||||
_adminManager.AdminStatusUpdated += UpdateButtons;
|
||||
UpdateButtons();
|
||||
|
||||
AdminOnly.OnToggled += args => PlaySound.Disabled = args.Pressed;
|
||||
|
||||
ChannelSelector.OnSelectionChanged += sel =>
|
||||
{
|
||||
_currentPlayer = sel;
|
||||
@@ -61,9 +57,9 @@ namespace Content.Client.Administration.UI.Bwoink
|
||||
var sb = new StringBuilder();
|
||||
|
||||
if (info.Connected)
|
||||
sb.Append(info.ActiveThisRound ? '⚫' : '◐');
|
||||
sb.Append('●');
|
||||
else
|
||||
sb.Append(info.ActiveThisRound ? '⭘' : '·');
|
||||
sb.Append(info.ActiveThisRound ? '○' : '·');
|
||||
|
||||
sb.Append(' ');
|
||||
if (AHelpHelper.TryGetChannel(info.SessionId, out var panel) && panel.Unread > 0)
|
||||
@@ -75,12 +71,10 @@ namespace Content.Client.Administration.UI.Bwoink
|
||||
sb.Append(' ');
|
||||
}
|
||||
|
||||
// Mark antagonists with symbol
|
||||
if (info.Antag && info.ActiveThisRound)
|
||||
sb.Append(new Rune(0x1F5E1)); // 🗡
|
||||
|
||||
// Mark new players with symbol
|
||||
if (IsNewPlayer(info))
|
||||
if (info.OverallPlaytime <= TimeSpan.FromMinutes(_cfg.GetCVar(CCVars.NewPlayerThreshold)))
|
||||
sb.Append(new Rune(0x23F2)); // ⏲
|
||||
|
||||
sb.AppendFormat("\"{0}\"", text);
|
||||
@@ -88,19 +82,6 @@ namespace Content.Client.Administration.UI.Bwoink
|
||||
return sb.ToString();
|
||||
};
|
||||
|
||||
// <summary>
|
||||
// Returns true if the player's overall playtime is under the set threshold
|
||||
// </summary>
|
||||
bool IsNewPlayer(PlayerInfo info)
|
||||
{
|
||||
// Don't show every disconnected player as new, don't show 0-minute players as new if threshold is
|
||||
if (newPlayerThreshold <= 0 || info.OverallPlaytime is null && !info.Connected)
|
||||
return false;
|
||||
|
||||
return (info.OverallPlaytime is null
|
||||
|| info.OverallPlaytime < TimeSpan.FromMinutes(newPlayerThreshold));
|
||||
}
|
||||
|
||||
ChannelSelector.Comparison = (a, b) =>
|
||||
{
|
||||
var ach = AHelpHelper.EnsurePanel(a.SessionId);
|
||||
@@ -110,37 +91,31 @@ namespace Content.Client.Administration.UI.Bwoink
|
||||
if (a.IsPinned != b.IsPinned)
|
||||
return a.IsPinned ? -1 : 1;
|
||||
|
||||
// Then, any chat with unread messages.
|
||||
// First, sort by unread. Any chat with unread messages appears first.
|
||||
var aUnread = ach.Unread > 0;
|
||||
var bUnread = bch.Unread > 0;
|
||||
if (aUnread != bUnread)
|
||||
return aUnread ? -1 : 1;
|
||||
|
||||
// Then, any chat with recent messages from the current round
|
||||
// Sort by recent messages during the current round.
|
||||
var aRecent = a.ActiveThisRound && ach.LastMessage != DateTime.MinValue;
|
||||
var bRecent = b.ActiveThisRound && bch.LastMessage != DateTime.MinValue;
|
||||
if (aRecent != bRecent)
|
||||
return aRecent ? -1 : 1;
|
||||
|
||||
// Sort by connection status. Disconnected players will be last.
|
||||
// Next, sort by connection status. Any disconnected players are grouped towards the end.
|
||||
if (a.Connected != b.Connected)
|
||||
return a.Connected ? -1 : 1;
|
||||
|
||||
// Sort connected players by whether they have joined the round, then by New Player status, then by Antag status
|
||||
// Sort connected players by New Player status, then by Antag status
|
||||
if (a.Connected && b.Connected)
|
||||
{
|
||||
var aNewPlayer = IsNewPlayer(a);
|
||||
var bNewPlayer = IsNewPlayer(b);
|
||||
var aNewPlayer = a.OverallPlaytime <= TimeSpan.FromMinutes(_cfg.GetCVar(CCVars.NewPlayerThreshold));
|
||||
var bNewPlayer = b.OverallPlaytime <= TimeSpan.FromMinutes(_cfg.GetCVar(CCVars.NewPlayerThreshold));
|
||||
|
||||
// Players who have joined the round will be listed before players in the lobby
|
||||
if (a.ActiveThisRound != b.ActiveThisRound)
|
||||
return a.ActiveThisRound ? -1 : 1;
|
||||
|
||||
// Within both the joined group and lobby group, new players will be grouped and listed first
|
||||
if (aNewPlayer != bNewPlayer)
|
||||
return aNewPlayer ? -1 : 1;
|
||||
|
||||
// Within all four previous groups, antagonists will be listed first.
|
||||
if (a.Antag != b.Antag)
|
||||
return a.Antag ? -1 : 1;
|
||||
}
|
||||
@@ -177,6 +152,11 @@ namespace Content.Client.Administration.UI.Bwoink
|
||||
|
||||
Kick.OnPressed += _ =>
|
||||
{
|
||||
if (!AdminUIHelpers.TryConfirm(Kick, _confirmations))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Reason field
|
||||
if (_currentPlayer is not null)
|
||||
_console.ExecuteCommand($"kick \"{_currentPlayer.Username}\"");
|
||||
@@ -190,6 +170,11 @@ namespace Content.Client.Administration.UI.Bwoink
|
||||
|
||||
Respawn.OnPressed += _ =>
|
||||
{
|
||||
if (!AdminUIHelpers.TryConfirm(Respawn, _confirmations))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_currentPlayer is not null)
|
||||
_console.ExecuteCommand($"respawn \"{_currentPlayer.Username}\"");
|
||||
};
|
||||
|
||||
@@ -22,9 +22,12 @@ namespace Content.Client.Administration.UI.Bwoink
|
||||
return;
|
||||
}
|
||||
|
||||
Title = $"{sel.CharacterName} / {sel.Username} | {Loc.GetString("generic-playtime-title")}: ";
|
||||
Title = $"{sel.CharacterName} / {sel.Username}";
|
||||
|
||||
Title += sel.OverallPlaytime != null ? sel.PlaytimeString : Loc.GetString("generic-unknown-title");
|
||||
if (sel.OverallPlaytime != null)
|
||||
{
|
||||
Title += $" | {Loc.GetString("generic-playtime-title")}: {sel.PlaytimeString}";
|
||||
}
|
||||
};
|
||||
|
||||
OnOpen += () =>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<Popup xmlns="https://spacestation14.io"
|
||||
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
|
||||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls">
|
||||
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client">
|
||||
<PanelContainer>
|
||||
<PanelContainer.PanelOverride>
|
||||
<gfx:StyleBoxFlat BorderThickness="2" BorderColor="#18181B" BackgroundColor="#25252a"/>
|
||||
@@ -20,7 +19,7 @@
|
||||
<BoxContainer Orientation="Horizontal">
|
||||
<Button Name="EditButton" Text="{Loc admin-notes-edit}"/>
|
||||
<Control HorizontalExpand="True"/>
|
||||
<controls:ConfirmButton Name="DeleteButton" Text="{Loc admin-notes-delete}" ConfirmationText="{Loc 'admin-player-actions-confirm'}" HorizontalAlignment="Right"/>
|
||||
<Button Name="DeleteButton" Text="{Loc admin-notes-delete}" HorizontalAlignment="Right"/>
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
</PanelContainer>
|
||||
|
||||
@@ -19,13 +19,12 @@
|
||||
<Label Name="SharedConnections"/>
|
||||
|
||||
<BoxContainer Align="Center">
|
||||
<GridContainer Rows="6">
|
||||
<GridContainer Rows="5">
|
||||
<Button Name="NotesButton" Text="{Loc player-panel-show-notes}" SetWidth="136" Disabled="True"/>
|
||||
<Button Name="AhelpButton" Text="{Loc player-panel-help}" Disabled="True"/>
|
||||
<Button Name="FreezeButton" Text = "{Loc player-panel-freeze}" Disabled="True"/>
|
||||
<controls:ConfirmButton Name="KickButton" Text="{Loc player-panel-kick}" Disabled="True"/>
|
||||
<controls:ConfirmButton Name="DeleteButton" Text="{Loc player-panel-delete}" Disabled="True"/>
|
||||
<Button Name="FollowButton" Text="{Loc player-panel-follow}"/>
|
||||
<Button Name="ShowBansButton" Text="{Loc player-panel-show-bans}" SetWidth="136" Disabled="True"/>
|
||||
<Button Name="LogsButton" Text="{Loc player-panel-logs}" Disabled="True"/>
|
||||
<Button Name="FreezeAndMuteToggleButton" Text="{Loc player-panel-freeze-and-mute}" Disabled="True"/>
|
||||
|
||||
@@ -2,6 +2,7 @@ using Content.Client.Administration.Managers;
|
||||
using Content.Client.UserInterface.Controls;
|
||||
using Content.Shared.Administration;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Utility;
|
||||
@@ -20,7 +21,6 @@ public sealed partial class PlayerPanel : FancyWindow
|
||||
public event Action<string?>? OnKick;
|
||||
public event Action<NetUserId?>? OnOpenBanPanel;
|
||||
public event Action<NetUserId?, bool>? OnWhitelistToggle;
|
||||
public event Action? OnFollow;
|
||||
public event Action? OnFreezeAndMuteToggle;
|
||||
public event Action? OnFreeze;
|
||||
public event Action? OnLogs;
|
||||
@@ -36,7 +36,7 @@ public sealed partial class PlayerPanel : FancyWindow
|
||||
RobustXamlLoader.Load(this);
|
||||
_adminManager = adminManager;
|
||||
|
||||
UsernameCopyButton.OnPressed += _ => OnUsernameCopy?.Invoke(TargetUsername ?? "");
|
||||
UsernameCopyButton.OnPressed += _ => OnUsernameCopy?.Invoke(PlayerName.Text ?? "");
|
||||
BanButton.OnPressed += _ => OnOpenBanPanel?.Invoke(TargetPlayer);
|
||||
KickButton.OnPressed += _ => OnKick?.Invoke(TargetUsername);
|
||||
NotesButton.OnPressed += _ => OnOpenNotes?.Invoke(TargetPlayer);
|
||||
@@ -47,7 +47,6 @@ public sealed partial class PlayerPanel : FancyWindow
|
||||
OnWhitelistToggle?.Invoke(TargetPlayer, _isWhitelisted);
|
||||
SetWhitelisted(!_isWhitelisted);
|
||||
};
|
||||
FollowButton.OnPressed += _ => OnFollow?.Invoke();
|
||||
FreezeButton.OnPressed += _ => OnFreeze?.Invoke();
|
||||
FreezeAndMuteToggleButton.OnPressed += _ => OnFreezeAndMuteToggle?.Invoke();
|
||||
LogsButton.OnPressed += _ => OnLogs?.Invoke();
|
||||
|
||||
@@ -38,7 +38,6 @@ public sealed class PlayerPanelEui : BaseEui
|
||||
PlayerPanel.OnLogs += () => SendMessage(new PlayerPanelLogsMessage());
|
||||
PlayerPanel.OnRejuvenate += () => SendMessage(new PlayerPanelRejuvenationMessage());
|
||||
PlayerPanel.OnDelete+= () => SendMessage(new PlayerPanelDeleteMessage());
|
||||
PlayerPanel.OnFollow += () => SendMessage(new PlayerPanelFollowMessage());
|
||||
|
||||
PlayerPanel.OnClose += () => SendMessage(new CloseEuiMessage());
|
||||
}
|
||||
|
||||
@@ -19,10 +19,10 @@ namespace Content.Client.Administration.UI.SpawnExplosion;
|
||||
public sealed partial class SpawnExplosionWindow : DefaultWindow
|
||||
{
|
||||
[Dependency] private readonly IClientConsoleHost _conHost = default!;
|
||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly IEntityManager _entMan = default!;
|
||||
private readonly SharedMapSystem _mapSystem;
|
||||
private readonly SharedTransformSystem _transform = default!;
|
||||
|
||||
private readonly SpawnExplosionEui _eui;
|
||||
@@ -38,7 +38,6 @@ public sealed partial class SpawnExplosionWindow : DefaultWindow
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
IoCManager.InjectDependencies(this);
|
||||
_mapSystem = _entMan.System<SharedMapSystem>();
|
||||
_transform = _entMan.System<TransformSystem>();
|
||||
_eui = eui;
|
||||
|
||||
@@ -88,7 +87,7 @@ public sealed partial class SpawnExplosionWindow : DefaultWindow
|
||||
{
|
||||
_mapData.Clear();
|
||||
MapOptions.Clear();
|
||||
foreach (var map in _mapSystem.GetAllMapIds())
|
||||
foreach (var map in _mapManager.GetAllMapIds())
|
||||
{
|
||||
_mapData.Add(map);
|
||||
MapOptions.AddItem(map.ToString());
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
<cc:UICommandButton Command="callshuttle" Text="{Loc admin-player-actions-window-shuttle}" WindowType="{x:Type at:AdminShuttleWindow}"/>
|
||||
<cc:CommandButton Command="adminlogs" Text="{Loc admin-player-actions-window-admin-logs}"/>
|
||||
<cc:CommandButton Command="faxui" Text="{Loc admin-player-actions-window-admin-fax}"/>
|
||||
<cc:CommandButton Command="achatwindow" Text="{Loc admin-player-actions-window-admin-chat}"/>
|
||||
</GridContainer>
|
||||
</BoxContainer>
|
||||
</Control>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<DefaultWindow
|
||||
xmlns="https://spacestation14.io"
|
||||
xmlns:cc="clr-namespace:Content.Client.Administration.UI.CustomControls"
|
||||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
||||
Title="{Loc admin-player-actions-window-title}" MinSize="425 272">
|
||||
<BoxContainer Orientation="Vertical">
|
||||
<BoxContainer Orientation="Horizontal">
|
||||
@@ -11,9 +10,9 @@
|
||||
</BoxContainer>
|
||||
<cc:PlayerListControl Name="PlayerList" VerticalExpand="True" />
|
||||
<BoxContainer Orientation="Horizontal">
|
||||
<controls:ConfirmButton Name="SubmitKickButton" Text="{Loc admin-player-actions-kick}" ConfirmationText="{Loc 'admin-player-actions-confirm'}" Disabled="True"/>
|
||||
<Button Name="SubmitKickButton" Text="{Loc admin-player-actions-kick}" Disabled="True"/>
|
||||
<Button Name="SubmitAHelpButton" Text="{Loc admin-player-actions-ahelp}" Disabled="True"/>
|
||||
<controls:ConfirmButton Name="SubmitRespawnButton" Text="{Loc admin-player-actions-respawn}" ConfirmationText="{Loc 'admin-player-actions-confirm'}" Disabled="True"/>
|
||||
<Button Name="SubmitRespawnButton" Text="{Loc admin-player-actions-respawn}" Disabled="True"/>
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
</DefaultWindow>
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Content.Client.Administration.UI.Tabs.AdminTab
|
||||
public sealed partial class PlayerActionsWindow : DefaultWindow
|
||||
{
|
||||
private PlayerInfo? _selectedPlayer;
|
||||
private readonly Dictionary<Button, ConfirmationData> _confirmations = new();
|
||||
|
||||
public PlayerActionsWindow()
|
||||
{
|
||||
@@ -27,6 +28,9 @@ namespace Content.Client.Administration.UI.Tabs.AdminTab
|
||||
|
||||
private void OnListOnOnSelectionChanged(PlayerInfo? obj)
|
||||
{
|
||||
if (_selectedPlayer != obj)
|
||||
AdminUIHelpers.RemoveAllConfirms(_confirmations);
|
||||
|
||||
_selectedPlayer = obj;
|
||||
var disableButtons = _selectedPlayer == null;
|
||||
SubmitKickButton.Disabled = disableButtons;
|
||||
@@ -39,6 +43,9 @@ namespace Content.Client.Administration.UI.Tabs.AdminTab
|
||||
if (_selectedPlayer == null)
|
||||
return;
|
||||
|
||||
if (!AdminUIHelpers.TryConfirm(SubmitKickButton, _confirmations))
|
||||
return;
|
||||
|
||||
IoCManager.Resolve<IClientConsoleHost>().ExecuteCommand(
|
||||
$"kick \"{_selectedPlayer.Username}\" \"{CommandParsing.Escape(ReasonLine.Text)}\"");
|
||||
}
|
||||
@@ -57,6 +64,9 @@ namespace Content.Client.Administration.UI.Tabs.AdminTab
|
||||
if (_selectedPlayer == null)
|
||||
return;
|
||||
|
||||
if (!AdminUIHelpers.TryConfirm(SubmitRespawnButton, _confirmations))
|
||||
return;
|
||||
|
||||
IoCManager.Resolve<IClientConsoleHost>().ExecuteCommand(
|
||||
$"respawn \"{_selectedPlayer.Username}\"");
|
||||
}
|
||||
|
||||
@@ -14,9 +14,6 @@ namespace Content.Client.Administration.UI.Tabs.AdminbusTab
|
||||
[UsedImplicitly]
|
||||
public sealed partial class LoadBlueprintsWindow : DefaultWindow
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
|
||||
public LoadBlueprintsWindow()
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
@@ -24,9 +21,9 @@ namespace Content.Client.Administration.UI.Tabs.AdminbusTab
|
||||
|
||||
protected override void EnteredTree()
|
||||
{
|
||||
var mapSystem = _entityManager.System<SharedMapSystem>();
|
||||
var mapManager = IoCManager.Resolve<IMapManager>();
|
||||
|
||||
foreach (var mapId in mapSystem.GetAllMapIds())
|
||||
foreach (var mapId in mapManager.GetAllMapIds())
|
||||
{
|
||||
MapOptions.AddItem(mapId.ToString(), (int) mapId);
|
||||
}
|
||||
@@ -42,19 +39,21 @@ namespace Content.Client.Administration.UI.Tabs.AdminbusTab
|
||||
|
||||
private void Reset()
|
||||
{
|
||||
var xformSystem = _entityManager.System<SharedTransformSystem>();
|
||||
var player = _playerManager.LocalEntity;
|
||||
var entManager = IoCManager.Resolve<IEntityManager>();
|
||||
var xformSystem = entManager.System<SharedTransformSystem>();
|
||||
var playerManager = IoCManager.Resolve<IPlayerManager>();
|
||||
var player = playerManager.LocalEntity;
|
||||
|
||||
var currentMap = MapId.Nullspace;
|
||||
var position = Vector2.Zero;
|
||||
var rotation = Angle.Zero;
|
||||
|
||||
if (_entityManager.TryGetComponent<TransformComponent>(player, out var xform))
|
||||
if (entManager.TryGetComponent<TransformComponent>(player, out var xform))
|
||||
{
|
||||
currentMap = xform.MapID;
|
||||
position = xformSystem.GetWorldPosition(xform);
|
||||
|
||||
if (_entityManager.TryGetComponent<TransformComponent>(xform.GridUid, out var gridXform))
|
||||
if (entManager.TryGetComponent<TransformComponent>(xform.GridUid, out var gridXform))
|
||||
{
|
||||
rotation = xformSystem.GetWorldRotation(gridXform);
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ public sealed partial class ObjectsTabEntry : PanelContainer
|
||||
|
||||
public Action<NetEntity>? OnTeleport;
|
||||
public Action<NetEntity>? OnDelete;
|
||||
private readonly Dictionary<Button, ConfirmationData> _confirmations = new();
|
||||
|
||||
public ObjectsTabEntry(IClientAdminManager manager, string name, NetEntity nent, StyleBox styleBox)
|
||||
{
|
||||
@@ -27,6 +28,13 @@ public sealed partial class ObjectsTabEntry : PanelContainer
|
||||
DeleteButton.Disabled = !manager.CanCommand("delete");
|
||||
|
||||
TeleportButton.OnPressed += _ => OnTeleport?.Invoke(nent);
|
||||
DeleteButton.OnPressed += _ => OnDelete?.Invoke(nent);
|
||||
DeleteButton.OnPressed += _ =>
|
||||
{
|
||||
if (!AdminUIHelpers.TryConfirm(DeleteButton, _confirmations))
|
||||
{
|
||||
return;
|
||||
}
|
||||
OnDelete?.Invoke(nent);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,13 +2,11 @@ using System.Linq;
|
||||
using Content.Client.Administration.Systems;
|
||||
using Content.Client.UserInterface.Controls;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.CCVar;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Configuration;
|
||||
using static Content.Client.Administration.UI.Tabs.PlayerTab.PlayerTabHeader;
|
||||
using static Robust.Client.UserInterface.Controls.BaseButton;
|
||||
|
||||
@@ -18,7 +16,6 @@ namespace Content.Client.Administration.UI.Tabs.PlayerTab;
|
||||
public sealed partial class PlayerTab : Control
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entManager = default!;
|
||||
[Dependency] private readonly IConfigurationManager _config = default!;
|
||||
[Dependency] private readonly IPlayerManager _playerMan = default!;
|
||||
|
||||
private const string ArrowUp = "↑";
|
||||
@@ -32,10 +29,6 @@ public sealed partial class PlayerTab : Control
|
||||
private bool _ascending = true;
|
||||
private bool _showDisconnected;
|
||||
|
||||
private AdminPlayerTabColorOption _playerTabColorSetting;
|
||||
private AdminPlayerTabRoleTypeOption _playerTabRoleSetting;
|
||||
private AdminPlayerTabSymbolOption _playerTabSymbolSetting;
|
||||
|
||||
public event Action<GUIBoundKeyEventArgs, ListData>? OnEntryKeyBindDown;
|
||||
|
||||
public PlayerTab()
|
||||
@@ -48,11 +41,6 @@ public sealed partial class PlayerTab : Control
|
||||
_adminSystem.OverlayEnabled += OverlayEnabled;
|
||||
_adminSystem.OverlayDisabled += OverlayDisabled;
|
||||
|
||||
_config.OnValueChanged(CCVars.AdminPlayerTabRoleSetting, RoleSettingChanged, true);
|
||||
_config.OnValueChanged(CCVars.AdminPlayerTabColorSetting, ColorSettingChanged, true);
|
||||
_config.OnValueChanged(CCVars.AdminPlayerTabSymbolSetting, SymbolSettingChanged, true);
|
||||
|
||||
|
||||
OverlayButton.OnPressed += OverlayButtonPressed;
|
||||
ShowDisconnectedButton.OnPressed += ShowDisconnectedPressed;
|
||||
|
||||
@@ -118,30 +106,6 @@ public sealed partial class PlayerTab : Control
|
||||
|
||||
#region ListContainer
|
||||
|
||||
private void RoleSettingChanged(string s)
|
||||
{
|
||||
if (!Enum.TryParse<AdminPlayerTabRoleTypeOption>(s, out var format))
|
||||
format = AdminPlayerTabRoleTypeOption.Subtype;
|
||||
_playerTabRoleSetting = format;
|
||||
RefreshPlayerList(_adminSystem.PlayerList);
|
||||
}
|
||||
|
||||
private void ColorSettingChanged(string s)
|
||||
{
|
||||
if (!Enum.TryParse<AdminPlayerTabColorOption>(s, out var format))
|
||||
format = AdminPlayerTabColorOption.Both;
|
||||
_playerTabColorSetting = format;
|
||||
RefreshPlayerList(_adminSystem.PlayerList);
|
||||
}
|
||||
|
||||
private void SymbolSettingChanged(string s)
|
||||
{
|
||||
if (!Enum.TryParse<AdminPlayerTabSymbolOption>(s, out var format))
|
||||
format = AdminPlayerTabSymbolOption.Specific;
|
||||
_playerTabSymbolSetting = format;
|
||||
RefreshPlayerList(_adminSystem.PlayerList);
|
||||
}
|
||||
|
||||
private void RefreshPlayerList(IReadOnlyList<PlayerInfo> players)
|
||||
{
|
||||
_players = players;
|
||||
@@ -164,12 +128,7 @@ public sealed partial class PlayerTab : Control
|
||||
if (data is not PlayerListData { Info: var player})
|
||||
return;
|
||||
|
||||
var entry = new PlayerTabEntry(
|
||||
player,
|
||||
new StyleBoxFlat(button.Index % 2 == 0 ? _altColor : _defaultColor),
|
||||
_playerTabColorSetting,
|
||||
_playerTabRoleSetting,
|
||||
_playerTabSymbolSetting);
|
||||
var entry = new PlayerTabEntry(player, new StyleBoxFlat(button.Index % 2 == 0 ? _altColor : _defaultColor));
|
||||
button.AddChild(entry);
|
||||
button.ToolTip = $"{player.Username}, {player.CharacterName}, {player.IdentityName}, {player.StartingJob}";
|
||||
}
|
||||
@@ -237,7 +196,8 @@ public sealed partial class PlayerTab : Control
|
||||
Header.Username => Compare(x.Username, y.Username),
|
||||
Header.Character => Compare(x.CharacterName, y.CharacterName),
|
||||
Header.Job => Compare(x.StartingJob, y.StartingJob),
|
||||
Header.RoleType => y.SortWeight - x.SortWeight,
|
||||
Header.Antagonist => x.Antag.CompareTo(y.Antag),
|
||||
Header.RoleType => Compare(x.RoleProto.Name , y.RoleProto.Name),
|
||||
Header.Playtime => TimeSpan.Compare(x.OverallPlaytime ?? default, y.OverallPlaytime ?? default),
|
||||
_ => 1
|
||||
};
|
||||
|
||||
@@ -19,6 +19,11 @@
|
||||
HorizontalExpand="True"
|
||||
ClipText="True"/>
|
||||
<customControls:VSeparator/>
|
||||
<Label Name="AntagonistLabel"
|
||||
SizeFlagsStretchRatio="1"
|
||||
HorizontalExpand="True"
|
||||
ClipText="True"/>
|
||||
<customControls:VSeparator/>
|
||||
<Label Name="RoleTypeLabel"
|
||||
SizeFlagsStretchRatio="2"
|
||||
HorizontalExpand="True"
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Roles;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
@@ -10,90 +9,24 @@ namespace Content.Client.Administration.UI.Tabs.PlayerTab;
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class PlayerTabEntry : PanelContainer
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entMan = default!;
|
||||
public NetEntity? PlayerEntity;
|
||||
|
||||
public PlayerTabEntry(
|
||||
PlayerInfo player,
|
||||
StyleBoxFlat styleBoxFlat,
|
||||
AdminPlayerTabColorOption colorOption,
|
||||
AdminPlayerTabRoleTypeOption roleSetting,
|
||||
AdminPlayerTabSymbolOption symbolSetting)
|
||||
public PlayerTabEntry(PlayerInfo player, StyleBoxFlat styleBoxFlat)
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
RobustXamlLoader.Load(this);
|
||||
var roles = _entMan.System<SharedRoleSystem>();
|
||||
|
||||
UsernameLabel.Text = player.Username;
|
||||
if (!player.Connected)
|
||||
UsernameLabel.StyleClasses.Add("Disabled");
|
||||
JobLabel.Text = player.StartingJob;
|
||||
|
||||
var colorAntags = false;
|
||||
var colorRoles = false;
|
||||
switch (colorOption)
|
||||
{
|
||||
case AdminPlayerTabColorOption.Off:
|
||||
break;
|
||||
case AdminPlayerTabColorOption.Character:
|
||||
colorAntags = true;
|
||||
break;
|
||||
case AdminPlayerTabColorOption.Roletype:
|
||||
colorRoles = true;
|
||||
break;
|
||||
default:
|
||||
case AdminPlayerTabColorOption.Both:
|
||||
colorAntags = true;
|
||||
colorRoles = true;
|
||||
break;
|
||||
}
|
||||
|
||||
var symbol = string.Empty;
|
||||
switch (symbolSetting)
|
||||
{
|
||||
case AdminPlayerTabSymbolOption.Off:
|
||||
break;
|
||||
case AdminPlayerTabSymbolOption.Basic:
|
||||
symbol = player.Antag ? Loc.GetString("player-tab-antag-prefix") : string.Empty;
|
||||
break;
|
||||
default:
|
||||
case AdminPlayerTabSymbolOption.Specific:
|
||||
symbol = player.Antag ? player.RoleProto.Symbol : string.Empty;
|
||||
break;
|
||||
}
|
||||
|
||||
CharacterLabel.Text = Loc.GetString("player-tab-character-name-antag-symbol", ("symbol", symbol), ("name", player.CharacterName));
|
||||
|
||||
if (player.Antag && colorAntags)
|
||||
CharacterLabel.FontColorOverride = player.RoleProto.Color;
|
||||
CharacterLabel.Text = player.CharacterName;
|
||||
if (player.IdentityName != player.CharacterName)
|
||||
CharacterLabel.Text += $" [{player.IdentityName}]";
|
||||
|
||||
var roletype = RoleTypeLabel.Text = Loc.GetString(player.RoleProto.Name);
|
||||
var subtype = roles.GetRoleSubtypeLabel(player.RoleProto.Name, player.Subtype);
|
||||
switch (roleSetting)
|
||||
{
|
||||
case AdminPlayerTabRoleTypeOption.RoleTypeSubtype:
|
||||
RoleTypeLabel.Text = roletype != subtype
|
||||
? roletype + " - " +subtype
|
||||
: roletype;
|
||||
break;
|
||||
case AdminPlayerTabRoleTypeOption.SubtypeRoleType:
|
||||
RoleTypeLabel.Text = roletype != subtype
|
||||
? subtype + " - " + roletype
|
||||
: roletype;
|
||||
break;
|
||||
case AdminPlayerTabRoleTypeOption.RoleType:
|
||||
RoleTypeLabel.Text = roletype;
|
||||
break;
|
||||
default:
|
||||
case AdminPlayerTabRoleTypeOption.Subtype:
|
||||
RoleTypeLabel.Text = subtype;
|
||||
break;
|
||||
}
|
||||
|
||||
if (colorRoles)
|
||||
RoleTypeLabel.FontColorOverride = player.RoleProto.Color;
|
||||
AntagonistLabel.Text = Loc.GetString(player.Antag ? "player-tab-is-antag-yes" : "player-tab-is-antag-no");
|
||||
RoleTypeLabel.Text = Loc.GetString(player.RoleProto.Name);
|
||||
RoleTypeLabel.FontColorOverride = player.RoleProto.Color;
|
||||
BackgroundColorPanel.PanelOverride = styleBoxFlat;
|
||||
OverallPlaytimeLabel.Text = player.PlaytimeString;
|
||||
PlayerEntity = player.NetEntity;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,13 @@
|
||||
Text="{Loc player-tab-job}"
|
||||
MouseFilter="Pass"/>
|
||||
<cc:VSeparator/>
|
||||
<Label Name="AntagonistLabel"
|
||||
SizeFlagsStretchRatio="1"
|
||||
HorizontalExpand="True"
|
||||
ClipText="True"
|
||||
Text="{Loc player-tab-antagonist}"
|
||||
MouseFilter="Pass"/>
|
||||
<cc:VSeparator/>
|
||||
<Label Name="RoleTypeLabel"
|
||||
SizeFlagsStretchRatio="2"
|
||||
HorizontalExpand="True"
|
||||
|
||||
@@ -18,6 +18,7 @@ public sealed partial class PlayerTabHeader : Control
|
||||
UsernameLabel.OnKeyBindDown += UsernameClicked;
|
||||
CharacterLabel.OnKeyBindDown += CharacterClicked;
|
||||
JobLabel.OnKeyBindDown += JobClicked;
|
||||
AntagonistLabel.OnKeyBindDown += AntagonistClicked;
|
||||
RoleTypeLabel.OnKeyBindDown += RoleTypeClicked;
|
||||
PlaytimeLabel.OnKeyBindDown += PlaytimeClicked;
|
||||
}
|
||||
@@ -29,6 +30,7 @@ public sealed partial class PlayerTabHeader : Control
|
||||
Header.Username => UsernameLabel,
|
||||
Header.Character => CharacterLabel,
|
||||
Header.Job => JobLabel,
|
||||
Header.Antagonist => AntagonistLabel,
|
||||
Header.RoleType => RoleTypeLabel,
|
||||
Header.Playtime => PlaytimeLabel,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(header), header, null)
|
||||
@@ -40,6 +42,7 @@ public sealed partial class PlayerTabHeader : Control
|
||||
UsernameLabel.Text = Loc.GetString("player-tab-username");
|
||||
CharacterLabel.Text = Loc.GetString("player-tab-character");
|
||||
JobLabel.Text = Loc.GetString("player-tab-job");
|
||||
AntagonistLabel.Text = Loc.GetString("player-tab-antagonist");
|
||||
RoleTypeLabel.Text = Loc.GetString("player-tab-roletype");
|
||||
PlaytimeLabel.Text = Loc.GetString("player-tab-playtime");
|
||||
}
|
||||
@@ -70,6 +73,11 @@ public sealed partial class PlayerTabHeader : Control
|
||||
HeaderClicked(args, Header.Job);
|
||||
}
|
||||
|
||||
private void AntagonistClicked(GUIBoundKeyEventArgs args)
|
||||
{
|
||||
HeaderClicked(args, Header.Antagonist);
|
||||
}
|
||||
|
||||
private void RoleTypeClicked(GUIBoundKeyEventArgs args)
|
||||
{
|
||||
HeaderClicked(args, Header.RoleType);
|
||||
@@ -89,6 +97,7 @@ public sealed partial class PlayerTabHeader : Control
|
||||
UsernameLabel.OnKeyBindDown -= UsernameClicked;
|
||||
CharacterLabel.OnKeyBindDown -= CharacterClicked;
|
||||
JobLabel.OnKeyBindDown -= JobClicked;
|
||||
AntagonistLabel.OnKeyBindDown -= AntagonistClicked;
|
||||
RoleTypeLabel.OnKeyBindDown -= RoleTypeClicked;
|
||||
PlaytimeLabel.OnKeyBindDown -= PlaytimeClicked;
|
||||
}
|
||||
@@ -99,6 +108,7 @@ public sealed partial class PlayerTabHeader : Control
|
||||
Username,
|
||||
Character,
|
||||
Job,
|
||||
Antagonist,
|
||||
RoleType,
|
||||
Playtime
|
||||
}
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
namespace Content.Client.Administration.UI.Tabs.PlayerTab;
|
||||
|
||||
public enum AdminPlayerTabColorOption
|
||||
{
|
||||
Off,
|
||||
Character,
|
||||
Roletype,
|
||||
Both
|
||||
}
|
||||
|
||||
public enum AdminPlayerTabRoleTypeOption
|
||||
{
|
||||
RoleType,
|
||||
Subtype,
|
||||
RoleTypeSubtype,
|
||||
SubtypeRoleType
|
||||
}
|
||||
|
||||
public enum AdminPlayerTabSymbolOption
|
||||
{
|
||||
Off,
|
||||
Basic,
|
||||
Specific
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
using Content.Shared.Advertise.Systems;
|
||||
|
||||
namespace Content.Client.Advertise.Systems;
|
||||
|
||||
public sealed class SpeakOnUIClosedSystem : SharedSpeakOnUIClosedSystem;
|
||||
@@ -8,8 +8,6 @@ namespace Content.Client.AlertLevel;
|
||||
|
||||
public sealed class AlertLevelDisplaySystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SpriteSystem _sprite = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
@@ -23,26 +21,26 @@ public sealed class AlertLevelDisplaySystem : EntitySystem
|
||||
{
|
||||
return;
|
||||
}
|
||||
var layer = _sprite.LayerMapReserve((uid, args.Sprite), AlertLevelDisplay.Layer);
|
||||
var layer = args.Sprite.LayerMapReserveBlank(AlertLevelDisplay.Layer);
|
||||
|
||||
if (args.AppearanceData.TryGetValue(AlertLevelDisplay.Powered, out var poweredObject))
|
||||
{
|
||||
_sprite.LayerSetVisible((uid, args.Sprite), layer, poweredObject is true);
|
||||
args.Sprite.LayerSetVisible(layer, poweredObject is true);
|
||||
}
|
||||
|
||||
if (!args.AppearanceData.TryGetValue(AlertLevelDisplay.CurrentLevel, out var level))
|
||||
{
|
||||
_sprite.LayerSetRsiState((uid, args.Sprite), layer, alertLevelDisplay.AlertVisuals.Values.First());
|
||||
args.Sprite.LayerSetState(layer, alertLevelDisplay.AlertVisuals.Values.First());
|
||||
return;
|
||||
}
|
||||
|
||||
if (alertLevelDisplay.AlertVisuals.TryGetValue((string)level, out var visual))
|
||||
if (alertLevelDisplay.AlertVisuals.TryGetValue((string) level, out var visual))
|
||||
{
|
||||
_sprite.LayerSetRsiState((uid, args.Sprite), layer, visual);
|
||||
args.Sprite.LayerSetState(layer, visual);
|
||||
}
|
||||
else
|
||||
{
|
||||
_sprite.LayerSetRsiState((uid, args.Sprite), layer, alertLevelDisplay.AlertVisuals.Values.First());
|
||||
args.Sprite.LayerSetState(layer, alertLevelDisplay.AlertVisuals.Values.First());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ using System.Linq;
|
||||
using Content.Shared.Alert;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Prototypes;
|
||||
@@ -16,7 +15,6 @@ public sealed class ClientAlertsSystem : AlertsSystem
|
||||
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly IUserInterfaceManager _ui = default!;
|
||||
|
||||
public event EventHandler? ClearAlerts;
|
||||
public event EventHandler<IReadOnlyDictionary<AlertKey, AlertState>>? SyncAlerts;
|
||||
@@ -29,12 +27,6 @@ public sealed class ClientAlertsSystem : AlertsSystem
|
||||
SubscribeLocalEvent<AlertsComponent, LocalPlayerDetachedEvent>(OnPlayerDetached);
|
||||
SubscribeLocalEvent<AlertsComponent, ComponentHandleState>(OnHandleState);
|
||||
}
|
||||
|
||||
protected override void HandledAlert()
|
||||
{
|
||||
_ui.ClickSound();
|
||||
}
|
||||
|
||||
protected override void LoadPrototypes()
|
||||
{
|
||||
base.LoadPrototypes();
|
||||
@@ -60,23 +52,7 @@ public sealed class ClientAlertsSystem : AlertsSystem
|
||||
if (args.Current is not AlertComponentState cast)
|
||||
return;
|
||||
|
||||
// Save all client-sided alerts to later put back in
|
||||
var clientAlerts = new Dictionary<AlertKey, AlertState>();
|
||||
foreach (var alert in alerts.Comp.Alerts)
|
||||
{
|
||||
if (alert.Key.AlertType != null && TryGet(alert.Key.AlertType.Value, out var alertProto))
|
||||
{
|
||||
if (alertProto.ClientHandled)
|
||||
clientAlerts[alert.Key] = alert.Value;
|
||||
}
|
||||
}
|
||||
|
||||
alerts.Comp.Alerts = new(cast.Alerts);
|
||||
|
||||
foreach (var alert in clientAlerts)
|
||||
{
|
||||
alerts.Comp.Alerts[alert.Key] = alert.Value;
|
||||
}
|
||||
alerts.Comp.Alerts = cast.Alerts;
|
||||
|
||||
UpdateHud(alerts);
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ public sealed class EntityPickupAnimationSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly AnimationPlayerSystem _animations = default!;
|
||||
[Dependency] private readonly MetaDataSystem _metaData = default!;
|
||||
[Dependency] private readonly SpriteSystem _sprite = default!;
|
||||
[Dependency] private readonly TransformSystem _transform = default!;
|
||||
|
||||
public override void Initialize()
|
||||
@@ -57,8 +56,8 @@ public sealed class EntityPickupAnimationSystem : EntitySystem
|
||||
}
|
||||
|
||||
var sprite = Comp<SpriteComponent>(animatableClone);
|
||||
_sprite.CopySprite((uid, sprite0), (animatableClone, sprite));
|
||||
_sprite.SetVisible((animatableClone, sprite), true);
|
||||
sprite.CopyFrom(sprite0);
|
||||
sprite.Visible = true;
|
||||
|
||||
var animations = Comp<AnimationPlayerComponent>(animatableClone);
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ public sealed class AnomalySystem : SharedAnomalySystem
|
||||
{
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
[Dependency] private readonly FloatingVisualizerSystem _floating = default!;
|
||||
[Dependency] private readonly SpriteSystem _sprite = default!;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Initialize()
|
||||
@@ -50,12 +49,12 @@ public sealed class AnomalySystem : SharedAnomalySystem
|
||||
if (HasComp<AnomalySupercriticalComponent>(uid))
|
||||
pulsing = true;
|
||||
|
||||
if (!_sprite.LayerMapTryGet((uid, sprite), AnomalyVisualLayers.Base, out var layer, false) ||
|
||||
!_sprite.LayerMapTryGet((uid, sprite), AnomalyVisualLayers.Animated, out var animatedLayer, false))
|
||||
if (!sprite.LayerMapTryGet(AnomalyVisualLayers.Base, out var layer) ||
|
||||
!sprite.LayerMapTryGet(AnomalyVisualLayers.Animated, out var animatedLayer))
|
||||
return;
|
||||
|
||||
_sprite.LayerSetVisible((uid, sprite), layer, !pulsing);
|
||||
_sprite.LayerSetVisible((uid, sprite), animatedLayer, pulsing);
|
||||
sprite.LayerSetVisible(layer, !pulsing);
|
||||
sprite.LayerSetVisible(animatedLayer, pulsing);
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
@@ -64,16 +63,16 @@ public sealed class AnomalySystem : SharedAnomalySystem
|
||||
|
||||
var query = EntityQueryEnumerator<AnomalySupercriticalComponent, SpriteComponent>();
|
||||
|
||||
while (query.MoveNext(out var uid, out var super, out var sprite))
|
||||
while (query.MoveNext(out var super, out var sprite))
|
||||
{
|
||||
var completion = 1f - (float)((super.EndTime - _timing.CurTime) / super.SupercriticalDuration);
|
||||
var completion = 1f - (float) ((super.EndTime - _timing.CurTime) / super.SupercriticalDuration);
|
||||
var scale = completion * (super.MaxScaleAmount - 1f) + 1f;
|
||||
_sprite.SetScale((uid, sprite), new Vector2(scale, scale));
|
||||
sprite.Scale = new Vector2(scale, scale);
|
||||
|
||||
var transparency = (byte)(65 * (1f - completion) + 190);
|
||||
var transparency = (byte) (65 * (1f - completion) + 190);
|
||||
if (transparency < sprite.Color.AByte)
|
||||
{
|
||||
_sprite.SetColor((uid, sprite), sprite.Color.WithAlpha(transparency));
|
||||
sprite.Color = sprite.Color.WithAlpha(transparency);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -83,7 +82,7 @@ public sealed class AnomalySystem : SharedAnomalySystem
|
||||
if (!TryComp<SpriteComponent>(ent, out var sprite))
|
||||
return;
|
||||
|
||||
_sprite.SetScale((ent.Owner, sprite), Vector2.One);
|
||||
_sprite.SetColor((ent.Owner, sprite), sprite.Color.WithAlpha(1f));
|
||||
sprite.Scale = Vector2.One;
|
||||
sprite.Color = sprite.Color.WithAlpha(1f);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,6 @@ namespace Content.Client.Anomaly.Effects;
|
||||
|
||||
public sealed class ClientInnerBodyAnomalySystem : SharedInnerBodyAnomalySystem
|
||||
{
|
||||
[Dependency] private readonly SpriteSystem _sprite = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<InnerBodyAnomalyComponent, AfterAutoHandleStateEvent>(OnAfterHandleState);
|
||||
@@ -23,20 +21,21 @@ public sealed class ClientInnerBodyAnomalySystem : SharedInnerBodyAnomalySystem
|
||||
if (ent.Comp.FallbackSprite is null)
|
||||
return;
|
||||
|
||||
var index = _sprite.LayerMapReserve((ent.Owner, sprite), ent.Comp.LayerMap);
|
||||
if (!sprite.LayerMapTryGet(ent.Comp.LayerMap, out var index))
|
||||
index = sprite.LayerMapReserveBlank(ent.Comp.LayerMap);
|
||||
|
||||
if (TryComp<BodyComponent>(ent, out var body) &&
|
||||
body.Prototype is not null &&
|
||||
ent.Comp.SpeciesSprites.TryGetValue(body.Prototype.Value, out var speciesSprite))
|
||||
{
|
||||
_sprite.LayerSetSprite((ent.Owner, sprite), index, speciesSprite);
|
||||
sprite.LayerSetSprite(index, speciesSprite);
|
||||
}
|
||||
else
|
||||
{
|
||||
_sprite.LayerSetSprite((ent.Owner, sprite), index, ent.Comp.FallbackSprite);
|
||||
sprite.LayerSetSprite(index, ent.Comp.FallbackSprite);
|
||||
}
|
||||
|
||||
_sprite.LayerSetVisible((ent.Owner, sprite), index, true);
|
||||
sprite.LayerSetVisible(index, true);
|
||||
sprite.LayerSetShader(index, "unshaded");
|
||||
}
|
||||
|
||||
@@ -45,7 +44,7 @@ public sealed class ClientInnerBodyAnomalySystem : SharedInnerBodyAnomalySystem
|
||||
if (!TryComp<SpriteComponent>(ent, out var sprite))
|
||||
return;
|
||||
|
||||
var index = _sprite.LayerMapGet((ent.Owner, sprite), ent.Comp.LayerMap);
|
||||
_sprite.LayerSetVisible((ent.Owner, sprite), index, false);
|
||||
var index = sprite.LayerMapGet(ent.Comp.LayerMap);
|
||||
sprite.LayerSetVisible(index, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,8 +11,6 @@ public sealed class AtmosAlertsComputerBoundUserInterface : BoundUserInterface
|
||||
|
||||
protected override void Open()
|
||||
{
|
||||
base.Open();
|
||||
|
||||
_menu = new AtmosAlertsComputerWindow(this, Owner);
|
||||
_menu.OpenCentered();
|
||||
_menu.OnClose += Close;
|
||||
|
||||
@@ -512,15 +512,39 @@ public sealed partial class AtmosAlertsComputerWindow : FancyWindow
|
||||
if (scroll == null)
|
||||
return;
|
||||
|
||||
if (!TryGetVerticalScrollbar(scroll, out var vScrollbar))
|
||||
return;
|
||||
|
||||
if (!TryGetNextScrollPosition(out float? nextScrollPosition))
|
||||
return;
|
||||
|
||||
scroll.VScrollTarget = nextScrollPosition.Value;
|
||||
vScrollbar.ValueTarget = nextScrollPosition.Value;
|
||||
|
||||
if (MathHelper.CloseToPercent(scroll.VScroll, scroll.VScrollTarget))
|
||||
if (MathHelper.CloseToPercent(vScrollbar.Value, vScrollbar.ValueTarget))
|
||||
_autoScrollActive = false;
|
||||
}
|
||||
|
||||
private bool TryGetVerticalScrollbar(ScrollContainer scroll, [NotNullWhen(true)] out VScrollBar? vScrollBar)
|
||||
{
|
||||
vScrollBar = null;
|
||||
|
||||
foreach (var child in scroll.Children)
|
||||
{
|
||||
if (child is not VScrollBar)
|
||||
continue;
|
||||
|
||||
var castChild = child as VScrollBar;
|
||||
|
||||
if (castChild != null)
|
||||
{
|
||||
vScrollBar = castChild;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool TryGetNextScrollPosition([NotNullWhen(true)] out float? nextScrollPosition)
|
||||
{
|
||||
nextScrollPosition = null;
|
||||
|
||||
@@ -350,15 +350,35 @@ public sealed partial class AtmosMonitoringConsoleWindow : FancyWindow
|
||||
if (scroll == null)
|
||||
return;
|
||||
|
||||
if (!TryGetVerticalScrollbar(scroll, out var vScrollbar))
|
||||
return;
|
||||
|
||||
if (!TryGetNextScrollPosition(out float? nextScrollPosition))
|
||||
return;
|
||||
|
||||
scroll.VScrollTarget = nextScrollPosition.Value;
|
||||
vScrollbar.ValueTarget = nextScrollPosition.Value;
|
||||
|
||||
if (MathHelper.CloseToPercent(scroll.VScroll, scroll.VScrollTarget))
|
||||
if (MathHelper.CloseToPercent(vScrollbar.Value, vScrollbar.ValueTarget))
|
||||
_autoScrollActive = false;
|
||||
}
|
||||
|
||||
private bool TryGetVerticalScrollbar(ScrollContainer scroll, [NotNullWhen(true)] out VScrollBar? vScrollBar)
|
||||
{
|
||||
vScrollBar = null;
|
||||
|
||||
foreach (var control in scroll.Children)
|
||||
{
|
||||
if (control is not VScrollBar)
|
||||
continue;
|
||||
|
||||
vScrollBar = (VScrollBar)control;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool TryGetNextScrollPosition([NotNullWhen(true)] out float? nextScrollPosition)
|
||||
{
|
||||
nextScrollPosition = null;
|
||||
|
||||
@@ -11,7 +11,6 @@ namespace Content.Client.Atmos.EntitySystems;
|
||||
public sealed class AtmosPipeAppearanceSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||
[Dependency] private readonly SpriteSystem _sprite = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -26,22 +25,21 @@ public sealed class AtmosPipeAppearanceSystem : EntitySystem
|
||||
if (!TryComp(uid, out SpriteComponent? sprite))
|
||||
return;
|
||||
|
||||
foreach (var layerKey in Enum.GetValues<PipeConnectionLayer>())
|
||||
foreach (PipeConnectionLayer layerKey in Enum.GetValues(typeof(PipeConnectionLayer)))
|
||||
{
|
||||
var layer = _sprite.LayerMapReserve((uid, sprite), layerKey);
|
||||
_sprite.LayerSetRsi((uid, sprite), layer, component.Sprite.RsiPath);
|
||||
_sprite.LayerSetRsiState((uid, sprite), layer, component.Sprite.RsiState);
|
||||
_sprite.LayerSetDirOffset((uid, sprite), layer, ToOffset(layerKey));
|
||||
sprite.LayerMapReserveBlank(layerKey);
|
||||
var layer = sprite.LayerMapGet(layerKey);
|
||||
sprite.LayerSetRSI(layer, component.Sprite.RsiPath);
|
||||
sprite.LayerSetState(layer, component.Sprite.RsiState);
|
||||
sprite.LayerSetDirOffset(layer, ToOffset(layerKey));
|
||||
}
|
||||
}
|
||||
|
||||
private void HideAllPipeConnection(Entity<SpriteComponent> entity)
|
||||
private void HideAllPipeConnection(SpriteComponent sprite)
|
||||
{
|
||||
var sprite = entity.Comp;
|
||||
|
||||
foreach (var layerKey in Enum.GetValues<PipeConnectionLayer>())
|
||||
foreach (PipeConnectionLayer layerKey in Enum.GetValues(typeof(PipeConnectionLayer)))
|
||||
{
|
||||
if (!_sprite.LayerMapTryGet(entity.AsNullable(), layerKey, out var key, false))
|
||||
if (!sprite.LayerMapTryGet(layerKey, out var key))
|
||||
continue;
|
||||
|
||||
var layer = sprite[key];
|
||||
@@ -63,7 +61,7 @@ public sealed class AtmosPipeAppearanceSystem : EntitySystem
|
||||
|
||||
if (!_appearance.TryGetData<PipeDirection>(uid, PipeVisuals.VisualState, out var worldConnectedDirections, args.Component))
|
||||
{
|
||||
HideAllPipeConnection((uid, args.Sprite));
|
||||
HideAllPipeConnection(args.Sprite);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -73,13 +71,13 @@ public sealed class AtmosPipeAppearanceSystem : EntitySystem
|
||||
// transform connected directions to local-coordinates
|
||||
var connectedDirections = worldConnectedDirections.RotatePipeDirection(-Transform(uid).LocalRotation);
|
||||
|
||||
foreach (var layerKey in Enum.GetValues<PipeConnectionLayer>())
|
||||
foreach (PipeConnectionLayer layerKey in Enum.GetValues(typeof(PipeConnectionLayer)))
|
||||
{
|
||||
if (!_sprite.LayerMapTryGet((uid, args.Sprite), layerKey, out var key, false))
|
||||
if (!args.Sprite.LayerMapTryGet(layerKey, out var key))
|
||||
continue;
|
||||
|
||||
var layer = args.Sprite[key];
|
||||
var dir = (PipeDirection)layerKey;
|
||||
var dir = (PipeDirection) layerKey;
|
||||
var visible = connectedDirections.HasDirection(dir);
|
||||
|
||||
layer.Visible &= visible;
|
||||
|
||||
@@ -2,7 +2,6 @@ using Content.Client.Atmos.Components;
|
||||
using Content.Shared.Atmos;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Client.Atmos.EntitySystems;
|
||||
|
||||
@@ -11,7 +10,6 @@ namespace Content.Client.Atmos.EntitySystems;
|
||||
/// </summary>
|
||||
public sealed class FireVisualizerSystem : VisualizerSystem<FireVisualsComponent>
|
||||
{
|
||||
[Dependency] private readonly SpriteSystem _sprite = default!;
|
||||
[Dependency] private readonly PointLightSystem _lights = default!;
|
||||
|
||||
public override void Initialize()
|
||||
@@ -33,9 +31,9 @@ public sealed class FireVisualizerSystem : VisualizerSystem<FireVisualsComponent
|
||||
// Need LayerMapTryGet because Init fails if there's no existing sprite / appearancecomp
|
||||
// which means in some setups (most frequently no AppearanceComp) the layer never exists.
|
||||
if (TryComp<SpriteComponent>(uid, out var sprite) &&
|
||||
_sprite.LayerMapTryGet((uid, sprite), FireVisualLayers.Fire, out var layer, false))
|
||||
sprite.LayerMapTryGet(FireVisualLayers.Fire, out var layer))
|
||||
{
|
||||
_sprite.RemoveLayer((uid, sprite), layer);
|
||||
sprite.RemoveLayer(layer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,11 +42,11 @@ public sealed class FireVisualizerSystem : VisualizerSystem<FireVisualsComponent
|
||||
if (!TryComp<SpriteComponent>(uid, out var sprite) || !TryComp(uid, out AppearanceComponent? appearance))
|
||||
return;
|
||||
|
||||
_sprite.LayerMapReserve((uid, sprite), FireVisualLayers.Fire);
|
||||
_sprite.LayerSetVisible((uid, sprite), FireVisualLayers.Fire, false);
|
||||
sprite.LayerMapReserveBlank(FireVisualLayers.Fire);
|
||||
sprite.LayerSetVisible(FireVisualLayers.Fire, false);
|
||||
sprite.LayerSetShader(FireVisualLayers.Fire, "unshaded");
|
||||
if (component.Sprite != null)
|
||||
_sprite.LayerSetRsi((uid, sprite), FireVisualLayers.Fire, new ResPath(component.Sprite));
|
||||
sprite.LayerSetRSI(FireVisualLayers.Fire, component.Sprite);
|
||||
|
||||
UpdateAppearance(uid, component, sprite, appearance);
|
||||
}
|
||||
@@ -61,12 +59,12 @@ public sealed class FireVisualizerSystem : VisualizerSystem<FireVisualsComponent
|
||||
|
||||
private void UpdateAppearance(EntityUid uid, FireVisualsComponent component, SpriteComponent sprite, AppearanceComponent appearance)
|
||||
{
|
||||
if (!_sprite.LayerMapTryGet((uid, sprite), FireVisualLayers.Fire, out var index, false))
|
||||
if (!sprite.LayerMapTryGet(FireVisualLayers.Fire, out var index))
|
||||
return;
|
||||
|
||||
AppearanceSystem.TryGetData<bool>(uid, FireVisuals.OnFire, out var onFire, appearance);
|
||||
AppearanceSystem.TryGetData<float>(uid, FireVisuals.FireStacks, out var fireStacks, appearance);
|
||||
_sprite.LayerSetVisible((uid, sprite), index, onFire);
|
||||
sprite.LayerSetVisible(index, onFire);
|
||||
|
||||
if (!onFire)
|
||||
{
|
||||
@@ -80,9 +78,9 @@ public sealed class FireVisualizerSystem : VisualizerSystem<FireVisualsComponent
|
||||
}
|
||||
|
||||
if (fireStacks > component.FireStackAlternateState && !string.IsNullOrEmpty(component.AlternateState))
|
||||
_sprite.LayerSetRsiState((uid, sprite), index, component.AlternateState);
|
||||
sprite.LayerSetState(index, component.AlternateState);
|
||||
else
|
||||
_sprite.LayerSetRsiState((uid, sprite), index, component.NormalState);
|
||||
sprite.LayerSetState(index, component.NormalState);
|
||||
|
||||
component.LightEntity ??= Spawn(null, new EntityCoordinates(uid, default));
|
||||
var light = EnsureComp<PointLightComponent>(component.LightEntity.Value);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Content.Client.Atmos.UI;
|
||||
using Content.Shared.Atmos.Components;
|
||||
using Content.Shared.Atmos.EntitySystems;
|
||||
using Content.Shared.Atmos.Piping.Binary.Components;
|
||||
@@ -14,12 +15,7 @@ public sealed class GasPressurePumpSystem : SharedGasPressurePumpSystem
|
||||
|
||||
private void OnPumpUpdate(Entity<GasPressurePumpComponent> ent, ref AfterAutoHandleStateEvent args)
|
||||
{
|
||||
UpdateUi(ent);
|
||||
}
|
||||
|
||||
protected override void UpdateUi(Entity<GasPressurePumpComponent> ent)
|
||||
{
|
||||
if (UserInterfaceSystem.TryGetOpenUi(ent.Owner, GasPressurePumpUiKey.Key, out var bui))
|
||||
if (UserInterfaceSystem.TryGetOpenUi<GasPressurePumpBoundUserInterface>(ent.Owner, GasPressurePumpUiKey.Key, out var bui))
|
||||
{
|
||||
bui.Update();
|
||||
}
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
using Content.Shared.Atmos.Components;
|
||||
using Content.Shared.Atmos.EntitySystems;
|
||||
|
||||
namespace Content.Client.Atmos.EntitySystems;
|
||||
|
||||
public sealed class GasTankSystem : SharedGasTankSystem
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<GasTankComponent, AfterAutoHandleStateEvent>(OnGasTankState);
|
||||
}
|
||||
|
||||
private void OnGasTankState(Entity<GasTankComponent> ent, ref AfterAutoHandleStateEvent args)
|
||||
{
|
||||
if (UI.TryGetOpenUi(ent.Owner, SharedGasTankUiKey.Key, out var bui))
|
||||
{
|
||||
bui.Update<GasTankBoundUserInterfaceState>();
|
||||
}
|
||||
}
|
||||
|
||||
public override void UpdateUserInterface(Entity<GasTankComponent> ent)
|
||||
{
|
||||
if (UI.TryGetOpenUi(ent.Owner, SharedGasTankUiKey.Key, out var bui))
|
||||
{
|
||||
bui.Update<GasTankBoundUserInterfaceState>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,6 @@ namespace Content.Client.Atmos.EntitySystems
|
||||
[Dependency] private readonly IResourceCache _resourceCache = default!;
|
||||
[Dependency] private readonly IOverlayManager _overlayMan = default!;
|
||||
[Dependency] private readonly SpriteSystem _spriteSys = default!;
|
||||
[Dependency] private readonly SharedTransformSystem _xformSys = default!;
|
||||
|
||||
private GasTileOverlay _overlay = default!;
|
||||
|
||||
@@ -26,7 +25,7 @@ namespace Content.Client.Atmos.EntitySystems
|
||||
SubscribeNetworkEvent<GasOverlayUpdateEvent>(HandleGasOverlayUpdate);
|
||||
SubscribeLocalEvent<GasTileOverlayComponent, ComponentHandleState>(OnHandleState);
|
||||
|
||||
_overlay = new GasTileOverlay(this, EntityManager, _resourceCache, ProtoMan, _spriteSys, _xformSys);
|
||||
_overlay = new GasTileOverlay(this, EntityManager, _resourceCache, ProtoMan, _spriteSys);
|
||||
_overlayMan.AddOverlay(_overlay);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,11 +7,9 @@ namespace Content.Client.Atmos.Monitor;
|
||||
|
||||
public sealed class AtmosAlarmableVisualsSystem : VisualizerSystem<AtmosAlarmableVisualsComponent>
|
||||
{
|
||||
[Dependency] private readonly SpriteSystem _sprite = default!;
|
||||
|
||||
protected override void OnAppearanceChange(EntityUid uid, AtmosAlarmableVisualsComponent component, ref AppearanceChangeEvent args)
|
||||
{
|
||||
if (args.Sprite == null || !_sprite.LayerMapTryGet((uid, args.Sprite), component.LayerMap, out var layer, false))
|
||||
if (args.Sprite == null || !args.Sprite.LayerMapTryGet(component.LayerMap, out var layer))
|
||||
return;
|
||||
|
||||
if (!args.AppearanceData.TryGetValue(PowerDeviceVisuals.Powered, out var poweredObject) ||
|
||||
@@ -24,8 +22,8 @@ public sealed class AtmosAlarmableVisualsSystem : VisualizerSystem<AtmosAlarmabl
|
||||
{
|
||||
foreach (var visLayer in component.HideOnDepowered)
|
||||
{
|
||||
if (_sprite.LayerMapTryGet((uid, args.Sprite), visLayer, out var powerVisibilityLayer, false))
|
||||
_sprite.LayerSetVisible((uid, args.Sprite), powerVisibilityLayer, powered);
|
||||
if (args.Sprite.LayerMapTryGet(visLayer, out var powerVisibilityLayer))
|
||||
args.Sprite.LayerSetVisible(powerVisibilityLayer, powered);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,8 +31,8 @@ public sealed class AtmosAlarmableVisualsSystem : VisualizerSystem<AtmosAlarmabl
|
||||
{
|
||||
foreach (var (setLayer, powerState) in component.SetOnDepowered)
|
||||
{
|
||||
if (_sprite.LayerMapTryGet((uid, args.Sprite), setLayer, out var setStateLayer, false))
|
||||
_sprite.LayerSetRsiState((uid, args.Sprite), setStateLayer, new RSI.StateId(powerState));
|
||||
if (args.Sprite.LayerMapTryGet(setLayer, out var setStateLayer))
|
||||
args.Sprite.LayerSetState(setStateLayer, new RSI.StateId(powerState));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +41,7 @@ public sealed class AtmosAlarmableVisualsSystem : VisualizerSystem<AtmosAlarmabl
|
||||
&& powered
|
||||
&& component.AlarmStates.TryGetValue(alarmType, out var state))
|
||||
{
|
||||
_sprite.LayerSetRsiState((uid, args.Sprite), layer, new RSI.StateId(state));
|
||||
args.Sprite.LayerSetState(layer, new RSI.StateId(state));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,13 +74,7 @@
|
||||
<!-- Mode buttons -->
|
||||
<BoxContainer Orientation="Horizontal">
|
||||
<Label Text="{Loc 'air-alarm-ui-window-mode-label'}" Margin="0 0 2 0" />
|
||||
<Control HorizontalExpand="True">
|
||||
<OptionButton Name="CModeButton" />
|
||||
<ui:StripeBack Name="CModeSelectLocked">
|
||||
<RichTextLabel Text="{Loc 'air-alarm-ui-window-mode-select-locked-label'}"
|
||||
HorizontalAlignment="Center" />
|
||||
</ui:StripeBack>
|
||||
</Control>
|
||||
<OptionButton Name="CModeButton" HorizontalExpand="True" />
|
||||
<CheckBox Name="AutoModeCheckBox" Text="{Loc 'air-alarm-ui-window-auto-mode-label'}" />
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
|
||||
@@ -103,15 +103,13 @@ public sealed partial class AirAlarmWindow : FancyWindow
|
||||
_temperature.SetMarkup(Loc.GetString("air-alarm-ui-window-temperature", ("tempC", $"{TemperatureHelpers.KelvinToCelsius(state.TemperatureAverage):0.#}"), ("temperature", $"{state.TemperatureAverage:0.##}")));
|
||||
_alarmState.SetMarkup(Loc.GetString("air-alarm-ui-window-alarm-state",
|
||||
("color", ColorForAlarm(state.AlarmType)),
|
||||
("state", state.AlarmType)));
|
||||
("state", $"{state.AlarmType}")));
|
||||
UpdateModeSelector(state.Mode);
|
||||
UpdateAutoMode(state.AutoMode);
|
||||
foreach (var (addr, dev) in state.DeviceData)
|
||||
{
|
||||
UpdateDeviceData(addr, dev);
|
||||
}
|
||||
_modes.Visible = !state.PanicWireCut;
|
||||
CModeSelectLocked.Visible = state.PanicWireCut;
|
||||
}
|
||||
|
||||
public void UpdateModeSelector(AirAlarmMode mode)
|
||||
|
||||
@@ -71,7 +71,6 @@ public sealed partial class ScrubberControl : BoxContainer
|
||||
_data.PumpDirection = (ScrubberPumpDirection) args.Id;
|
||||
ScrubberDataChanged?.Invoke(_address, _data);
|
||||
};
|
||||
_pumpDirection.Disabled = data.AirAlarmPanicWireCut;
|
||||
|
||||
_copySettings.OnPressed += _ =>
|
||||
{
|
||||
@@ -110,7 +109,6 @@ public sealed partial class ScrubberControl : BoxContainer
|
||||
|
||||
_data.PumpDirection = data.PumpDirection;
|
||||
_pumpDirection.Select((int) _data.PumpDirection);
|
||||
_pumpDirection.Disabled = data.AirAlarmPanicWireCut;
|
||||
|
||||
_data.VolumeRate = data.VolumeRate;
|
||||
_volumeRate.Value = _data.VolumeRate;
|
||||
|
||||
@@ -27,11 +27,11 @@ public sealed partial class SensorInfo : BoxContainer
|
||||
|
||||
_address = address;
|
||||
|
||||
SensorAddress.Title = Loc.GetString("air-alarm-ui-window-listing-title", ("address", _address), ("state", data.AlarmState));
|
||||
SensorAddress.Title = $"{address} : {data.AlarmState}";
|
||||
|
||||
AlarmStateLabel.SetMarkup(Loc.GetString("air-alarm-ui-window-alarm-state-indicator",
|
||||
("color", AirAlarmWindow.ColorForAlarm(data.AlarmState)),
|
||||
("state", data.AlarmState)));
|
||||
("state", $"{data.AlarmState}")));
|
||||
PressureLabel.SetMarkup(Loc.GetString("air-alarm-ui-window-pressure-indicator",
|
||||
("color", AirAlarmWindow.ColorForThreshold(data.Pressure, data.PressureThreshold)),
|
||||
("pressure", $"{data.Pressure:0.##}")));
|
||||
@@ -90,11 +90,11 @@ public sealed partial class SensorInfo : BoxContainer
|
||||
|
||||
public void ChangeData(AtmosSensorData data)
|
||||
{
|
||||
SensorAddress.Title = Loc.GetString("air-alarm-ui-window-listing-title", ("address", _address), ("state", data.AlarmState));
|
||||
SensorAddress.Title = $"{_address} : {data.AlarmState}";
|
||||
|
||||
AlarmStateLabel.SetMarkup(Loc.GetString("air-alarm-ui-window-alarm-state-indicator",
|
||||
("color", AirAlarmWindow.ColorForAlarm(data.AlarmState)),
|
||||
("state", data.AlarmState)));
|
||||
("state", $"{data.AlarmState}")));
|
||||
|
||||
PressureLabel.SetMarkup(Loc.GetString("air-alarm-ui-window-pressure-indicator",
|
||||
("color", AirAlarmWindow.ColorForThreshold(data.Pressure, data.PressureThreshold)),
|
||||
|
||||
@@ -21,8 +21,6 @@ namespace Content.Client.Atmos.Overlays
|
||||
{
|
||||
private readonly IEntityManager _entManager;
|
||||
private readonly IMapManager _mapManager;
|
||||
private readonly SharedMapSystem _mapSystem;
|
||||
private readonly SharedTransformSystem _xformSys;
|
||||
|
||||
public override OverlaySpace Space => OverlaySpace.WorldSpaceEntities | OverlaySpace.WorldSpaceBelowWorld;
|
||||
private readonly ShaderInstance _shader;
|
||||
@@ -48,12 +46,10 @@ namespace Content.Client.Atmos.Overlays
|
||||
|
||||
public const int GasOverlayZIndex = (int) Shared.DrawDepth.DrawDepth.Effects; // Under ghosts, above mostly everything else
|
||||
|
||||
public GasTileOverlay(GasTileOverlaySystem system, IEntityManager entManager, IResourceCache resourceCache, IPrototypeManager protoMan, SpriteSystem spriteSys, SharedTransformSystem xformSys)
|
||||
public GasTileOverlay(GasTileOverlaySystem system, IEntityManager entManager, IResourceCache resourceCache, IPrototypeManager protoMan, SpriteSystem spriteSys)
|
||||
{
|
||||
_entManager = entManager;
|
||||
_mapManager = IoCManager.Resolve<IMapManager>();
|
||||
_mapSystem = entManager.System<SharedMapSystem>();
|
||||
_xformSys = xformSys;
|
||||
_shader = protoMan.Index<ShaderPrototype>("unshaded").Instance();
|
||||
ZIndex = GasOverlayZIndex;
|
||||
|
||||
@@ -162,10 +158,9 @@ namespace Content.Client.Atmos.Overlays
|
||||
_fireFrameCounter,
|
||||
_shader,
|
||||
overlayQuery,
|
||||
xformQuery,
|
||||
_xformSys);
|
||||
xformQuery);
|
||||
|
||||
var mapUid = _mapSystem.GetMapOrInvalid(args.MapId);
|
||||
var mapUid = _mapManager.GetMapEntityId(args.MapId);
|
||||
|
||||
if (_entManager.TryGetComponent<MapAtmosphereComponent>(mapUid, out var atmos))
|
||||
DrawMapOverlay(drawHandle, args, mapUid, atmos);
|
||||
@@ -185,8 +180,7 @@ namespace Content.Client.Atmos.Overlays
|
||||
int[] fireFrameCounter,
|
||||
ShaderInstance shader,
|
||||
EntityQuery<GasTileOverlayComponent> overlayQuery,
|
||||
EntityQuery<TransformComponent> xformQuery,
|
||||
SharedTransformSystem xformSys) state) =>
|
||||
EntityQuery<TransformComponent> xformQuery) state) =>
|
||||
{
|
||||
if (!state.overlayQuery.TryGetComponent(uid, out var comp) ||
|
||||
!state.xformQuery.TryGetComponent(uid, out var gridXform))
|
||||
@@ -194,7 +188,7 @@ namespace Content.Client.Atmos.Overlays
|
||||
return true;
|
||||
}
|
||||
|
||||
var (_, _, worldMatrix, invMatrix) = state.xformSys.GetWorldPositionRotationMatrixWithInv(gridXform);
|
||||
var (_, _, worldMatrix, invMatrix) = gridXform.GetWorldPositionRotationMatrixWithInv();
|
||||
state.drawHandle.SetTransform(worldMatrix);
|
||||
var floatBounds = invMatrix.TransformBox(state.WorldBounds).Enlarged(grid.TileSize);
|
||||
var localBounds = new Box2i(
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
using Content.Shared.Atmos.Piping.Binary.Systems;
|
||||
|
||||
namespace Content.Client.Atmos.Piping.Binary.Systems;
|
||||
|
||||
public sealed class GasValveSystem : SharedGasValveSystem
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
using Content.Shared.Atmos.Piping.Binary.Components;
|
||||
using Content.Shared.Atmos.Piping.Binary.Systems;
|
||||
using Robust.Client.GameObjects;
|
||||
|
||||
namespace Content.Client.Atmos.Piping.Binary.Systems;
|
||||
|
||||
public sealed class GasVolumePumpSystem : SharedGasVolumePumpSystem
|
||||
{
|
||||
[Dependency] private readonly UserInterfaceSystem _ui = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<GasVolumePumpComponent, AfterAutoHandleStateEvent>(OnPumpState);
|
||||
}
|
||||
|
||||
protected override void UpdateUi(Entity<GasVolumePumpComponent> entity)
|
||||
{
|
||||
if (_ui.TryGetOpenUi(entity.Owner, GasVolumePumpUiKey.Key, out var bui))
|
||||
{
|
||||
bui.Update();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPumpState(Entity<GasVolumePumpComponent> ent, ref AfterAutoHandleStateEvent args)
|
||||
{
|
||||
UpdateUi(ent);
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
using Content.Client.Atmos.UI;
|
||||
using Content.Shared.Atmos.Piping.Binary.Components;
|
||||
using Content.Shared.Atmos.Piping.Unary.Components;
|
||||
using Content.Shared.Atmos.Piping.Unary.Systems;
|
||||
using Content.Shared.NodeContainer;
|
||||
|
||||
namespace Content.Client.Atmos.Piping.Unary.Systems;
|
||||
|
||||
public sealed class GasCanisterSystem : SharedGasCanisterSystem
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<GasCanisterComponent, AfterAutoHandleStateEvent>(OnGasState);
|
||||
}
|
||||
|
||||
private void OnGasState(Entity<GasCanisterComponent> ent, ref AfterAutoHandleStateEvent args)
|
||||
{
|
||||
if (UI.TryGetOpenUi<GasCanisterBoundUserInterface>(ent.Owner, GasCanisterUiKey.Key, out var bui))
|
||||
{
|
||||
bui.Update<GasCanisterBoundUserInterfaceState>();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void DirtyUI(EntityUid uid, GasCanisterComponent? component = null, NodeContainerComponent? nodes = null)
|
||||
{
|
||||
if (UI.TryGetOpenUi<GasCanisterBoundUserInterface>(uid, GasCanisterUiKey.Key, out var bui))
|
||||
{
|
||||
bui.Update<GasCanisterBoundUserInterfaceState>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
using Content.Client.Atmos.UI;
|
||||
using Content.Shared.Atmos.Piping.Unary.Components;
|
||||
using Content.Shared.Atmos.Piping.Unary.Systems;
|
||||
|
||||
namespace Content.Client.Atmos.Piping.Unary.Systems;
|
||||
|
||||
public sealed class GasThermoMachineSystem : SharedGasThermoMachineSystem
|
||||
{
|
||||
[Dependency] private readonly SharedUserInterfaceSystem _ui = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<GasThermoMachineComponent, AfterAutoHandleStateEvent>(OnGasAfterState);
|
||||
}
|
||||
|
||||
private void OnGasAfterState(Entity<GasThermoMachineComponent> ent, ref AfterAutoHandleStateEvent args)
|
||||
{
|
||||
DirtyUI(ent.Owner, ent.Comp);
|
||||
}
|
||||
|
||||
protected override void DirtyUI(EntityUid uid, GasThermoMachineComponent? thermoMachine, UserInterfaceComponent? ui = null)
|
||||
{
|
||||
if (_ui.TryGetOpenUi<GasThermomachineBoundUserInterface>(uid, ThermomachineUiKey.Key, out var bui))
|
||||
{
|
||||
bui.Update();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.UserInterface;
|
||||
using static Content.Shared.Atmos.Components.GasAnalyzerComponent;
|
||||
|
||||
namespace Content.Client.Atmos.UI
|
||||
@@ -17,7 +16,9 @@ namespace Content.Client.Atmos.UI
|
||||
{
|
||||
base.Open();
|
||||
|
||||
_window = this.CreateWindowCenteredLeft<GasAnalyzerWindow>();
|
||||
_window = new GasAnalyzerWindow();
|
||||
_window.OnClose += OnClose;
|
||||
_window.OpenCenteredLeft();
|
||||
}
|
||||
|
||||
protected override void ReceiveMessage(BoundUserInterfaceMessage message)
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
using Content.Shared.Atmos.Components;
|
||||
using Content.Shared.Atmos.Piping.Binary.Components;
|
||||
using Content.Shared.Atmos.Piping.Unary.Components;
|
||||
using Content.Shared.IdentityManagement;
|
||||
using Content.Shared.Atmos.Piping.Binary.Components;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.UserInterface;
|
||||
@@ -35,22 +32,22 @@ namespace Content.Client.Atmos.UI
|
||||
|
||||
private void OnTankEjectPressed()
|
||||
{
|
||||
SendPredictedMessage(new GasCanisterHoldingTankEjectMessage());
|
||||
SendMessage(new GasCanisterHoldingTankEjectMessage());
|
||||
}
|
||||
|
||||
private void OnReleasePressureSet(float value)
|
||||
{
|
||||
SendPredictedMessage(new GasCanisterChangeReleasePressureMessage(value));
|
||||
SendMessage(new GasCanisterChangeReleasePressureMessage(value));
|
||||
}
|
||||
|
||||
private void OnReleaseValveOpenPressed()
|
||||
{
|
||||
SendPredictedMessage(new GasCanisterChangeReleaseValveMessage(true));
|
||||
SendMessage(new GasCanisterChangeReleaseValveMessage(true));
|
||||
}
|
||||
|
||||
private void OnReleaseValveClosePressed()
|
||||
{
|
||||
SendPredictedMessage(new GasCanisterChangeReleaseValveMessage(false));
|
||||
SendMessage(new GasCanisterChangeReleaseValveMessage(false));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -60,21 +57,17 @@ namespace Content.Client.Atmos.UI
|
||||
protected override void UpdateState(BoundUserInterfaceState state)
|
||||
{
|
||||
base.UpdateState(state);
|
||||
if (_window == null || state is not GasCanisterBoundUserInterfaceState cast || !EntMan.TryGetComponent(Owner, out GasCanisterComponent? component))
|
||||
if (_window == null || state is not GasCanisterBoundUserInterfaceState cast)
|
||||
return;
|
||||
|
||||
var canisterLabel = Identity.Name(Owner, EntMan);
|
||||
var tankLabel = component.GasTankSlot.Item != null ? Identity.Name(component.GasTankSlot.Item.Value, EntMan) : null;
|
||||
|
||||
_window.SetCanisterLabel(canisterLabel);
|
||||
_window.SetCanisterLabel(cast.CanisterLabel);
|
||||
_window.SetCanisterPressure(cast.CanisterPressure);
|
||||
_window.SetPortStatus(cast.PortStatus);
|
||||
|
||||
_window.SetTankLabel(tankLabel);
|
||||
_window.SetTankLabel(cast.TankLabel);
|
||||
_window.SetTankPressure(cast.TankPressure);
|
||||
_window.SetReleasePressureRange(component.MinReleasePressure, component.MaxReleasePressure);
|
||||
_window.SetReleasePressure(component.ReleasePressure);
|
||||
_window.SetReleaseValve(component.ReleaseValve);
|
||||
_window.SetReleasePressureRange(cast.ReleasePressureMin, cast.ReleasePressureMax);
|
||||
_window.SetReleasePressure(cast.ReleasePressure);
|
||||
_window.SetReleaseValve(cast.ReleaseValve);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Atmos.Components;
|
||||
using Content.Shared.Atmos.Piping.Binary.Components;
|
||||
using Content.Shared.IdentityManagement;
|
||||
using Content.Shared.Localizations;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.UserInterface;
|
||||
|
||||
@@ -11,11 +12,18 @@ namespace Content.Client.Atmos.UI;
|
||||
/// Initializes a <see cref="GasPressurePumpWindow"/> and updates it when new server messages are received.
|
||||
/// </summary>
|
||||
[UsedImplicitly]
|
||||
public sealed class GasPressurePumpBoundUserInterface(EntityUid owner, Enum uiKey) : BoundUserInterface(owner, uiKey)
|
||||
public sealed class GasPressurePumpBoundUserInterface : BoundUserInterface
|
||||
{
|
||||
[ViewVariables]
|
||||
private const float MaxPressure = Atmospherics.MaxOutputPressure;
|
||||
|
||||
[ViewVariables]
|
||||
private GasPressurePumpWindow? _window;
|
||||
|
||||
public GasPressurePumpBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Open()
|
||||
{
|
||||
base.Open();
|
||||
@@ -27,7 +35,7 @@ public sealed class GasPressurePumpBoundUserInterface(EntityUid owner, Enum uiKe
|
||||
Update();
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
public void Update()
|
||||
{
|
||||
if (_window == null)
|
||||
return;
|
||||
@@ -44,9 +52,7 @@ public sealed class GasPressurePumpBoundUserInterface(EntityUid owner, Enum uiKe
|
||||
|
||||
private void OnToggleStatusButtonPressed()
|
||||
{
|
||||
if (_window is null)
|
||||
return;
|
||||
|
||||
if (_window is null) return;
|
||||
SendPredictedMessage(new GasPressurePumpToggleStatusMessage(_window.PumpStatus));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Content.Client.UserInterface.Controls;
|
||||
using Content.Shared.Atmos;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
|
||||
namespace Content.Client.Atmos.UI
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
using Content.Client.Power.EntitySystems;
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Atmos.Piping.Unary.Components;
|
||||
using Content.Shared.Atmos.Piping.Unary.Systems;
|
||||
using Content.Shared.Power.Components;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.UserInterface;
|
||||
@@ -39,8 +36,6 @@ namespace Content.Client.Atmos.UI
|
||||
|
||||
_window.ToggleStatusButton.OnPressed += _ => OnToggleStatusButtonPressed();
|
||||
_window.TemperatureSpinbox.OnValueChanged += _ => OnTemperatureChanged(_window.TemperatureSpinbox.Value);
|
||||
_window.Entity = Owner;
|
||||
Update();
|
||||
}
|
||||
|
||||
private void OnToggleStatusButtonPressed()
|
||||
@@ -48,7 +43,7 @@ namespace Content.Client.Atmos.UI
|
||||
if (_window is null) return;
|
||||
|
||||
_window.SetActive(!_window.Active);
|
||||
SendPredictedMessage(new GasThermomachineToggleMessage());
|
||||
SendMessage(new GasThermomachineToggleMessage());
|
||||
}
|
||||
|
||||
private void OnTemperatureChanged(float value)
|
||||
@@ -65,32 +60,25 @@ namespace Content.Client.Atmos.UI
|
||||
return;
|
||||
}
|
||||
|
||||
SendPredictedMessage(new GasThermomachineChangeTemperatureMessage(actual));
|
||||
SendMessage(new GasThermomachineChangeTemperatureMessage(actual));
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
/// <summary>
|
||||
/// Update the UI state based on server-sent info
|
||||
/// </summary>
|
||||
/// <param name="state"></param>
|
||||
protected override void UpdateState(BoundUserInterfaceState state)
|
||||
{
|
||||
if (_window == null || !EntMan.TryGetComponent(Owner, out GasThermoMachineComponent? thermo))
|
||||
base.UpdateState(state);
|
||||
if (_window == null || state is not GasThermomachineBoundUserInterfaceState cast)
|
||||
return;
|
||||
|
||||
var system = EntMan.System<SharedGasThermoMachineSystem>();
|
||||
_minTemp = thermo.MinTemperature;
|
||||
_maxTemp = thermo.MaxTemperature;
|
||||
_isHeater = system.IsHeater(thermo);
|
||||
|
||||
_window.SetTemperature(thermo.TargetTemperature);
|
||||
|
||||
var receiverSys = EntMan.System<PowerReceiverSystem>();
|
||||
SharedApcPowerReceiverComponent? receiver = null;
|
||||
|
||||
receiverSys.ResolveApc(Owner, ref receiver);
|
||||
|
||||
// Also set in frameupdates.
|
||||
if (receiver != null)
|
||||
{
|
||||
_window.SetActive(!receiver.PowerDisabled);
|
||||
}
|
||||
_minTemp = cast.MinTemperature;
|
||||
_maxTemp = cast.MaxTemperature;
|
||||
_isHeater = cast.IsHeater;
|
||||
|
||||
_window.SetTemperature(cast.Temperature);
|
||||
_window.SetActive(cast.Enabled);
|
||||
_window.Title = _isHeater switch
|
||||
{
|
||||
false => Loc.GetString("comp-gas-thermomachine-ui-title-freezer"),
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<controls:FancyWindow xmlns="https://spacestation14.io"
|
||||
<DefaultWindow xmlns="https://spacestation14.io"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
||||
MinSize="300 120" Title="{Loc comp-gas-thermomachine-ui-title-freezer}">
|
||||
<BoxContainer Name="VboxContainer" Orientation="Vertical" Margin="5 5 5 5" SeparationOverride="10">
|
||||
<BoxContainer Orientation="Horizontal" HorizontalExpand="True">
|
||||
@@ -12,4 +11,4 @@
|
||||
<Label Text="{Loc comp-gas-thermomachine-ui-temperature}"/>
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
</controls:FancyWindow>
|
||||
</DefaultWindow>
|
||||
|
||||
@@ -1,26 +1,19 @@
|
||||
using Content.Client.Power.Components;
|
||||
using Content.Client.UserInterface.Controls;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Client.Atmos.UI;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class GasThermomachineWindow : FancyWindow
|
||||
public sealed partial class GasThermomachineWindow : DefaultWindow
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entManager = default!;
|
||||
|
||||
public bool Active = true;
|
||||
|
||||
public FloatSpinBox TemperatureSpinbox;
|
||||
|
||||
public EntityUid Entity;
|
||||
|
||||
public GasThermomachineWindow()
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
RobustXamlLoader.Load(this);
|
||||
|
||||
SpinboxHBox.AddChild(
|
||||
@@ -34,10 +27,12 @@ public sealed partial class GasThermomachineWindow : FancyWindow
|
||||
if (active)
|
||||
{
|
||||
ToggleStatusButton.Text = Loc.GetString("comp-gas-thermomachine-ui-status-enabled");
|
||||
ToggleStatusButton.Pressed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ToggleStatusButton.Text = Loc.GetString("comp-gas-thermomachine-ui-status-disabled");
|
||||
ToggleStatusButton.Pressed = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,14 +40,4 @@ public sealed partial class GasThermomachineWindow : FancyWindow
|
||||
{
|
||||
TemperatureSpinbox.Value = temperature;
|
||||
}
|
||||
|
||||
protected override void FrameUpdate(FrameEventArgs args)
|
||||
{
|
||||
base.FrameUpdate(args);
|
||||
|
||||
if (_entManager.TryGetComponent(Entity, out ApcPowerReceiverComponent? receiver))
|
||||
{
|
||||
SetActive(!receiver.PowerDisabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
using Content.Shared.Atmos.Piping.Binary.Components;
|
||||
using Content.Shared.IdentityManagement;
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Atmos.Piping.Binary.Components;
|
||||
using Content.Shared.Localizations;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.UserInterface;
|
||||
|
||||
namespace Content.Client.Atmos.UI
|
||||
@@ -13,7 +14,7 @@ namespace Content.Client.Atmos.UI
|
||||
public sealed class GasVolumePumpBoundUserInterface : BoundUserInterface
|
||||
{
|
||||
[ViewVariables]
|
||||
private float _maxTransferRate;
|
||||
private const float MaxTransferRate = Atmospherics.MaxTransferRate;
|
||||
|
||||
[ViewVariables]
|
||||
private GasVolumePumpWindow? _window;
|
||||
@@ -28,41 +29,38 @@ namespace Content.Client.Atmos.UI
|
||||
|
||||
_window = this.CreateWindow<GasVolumePumpWindow>();
|
||||
|
||||
if (EntMan.TryGetComponent(Owner, out GasVolumePumpComponent? pump))
|
||||
{
|
||||
_maxTransferRate = pump.MaxTransferRate;
|
||||
}
|
||||
|
||||
_window.ToggleStatusButtonPressed += OnToggleStatusButtonPressed;
|
||||
_window.PumpTransferRateChanged += OnPumpTransferRatePressed;
|
||||
Update();
|
||||
}
|
||||
|
||||
private void OnToggleStatusButtonPressed()
|
||||
{
|
||||
if (_window is null) return;
|
||||
|
||||
SendPredictedMessage(new GasVolumePumpToggleStatusMessage(_window.PumpStatus));
|
||||
SendMessage(new GasVolumePumpToggleStatusMessage(_window.PumpStatus));
|
||||
}
|
||||
|
||||
private void OnPumpTransferRatePressed(string value)
|
||||
{
|
||||
var rate = UserInputParser.TryFloat(value, out var parsed) ? parsed : 0f;
|
||||
rate = Math.Clamp(rate, 0f, _maxTransferRate);
|
||||
if (rate > MaxTransferRate)
|
||||
rate = MaxTransferRate;
|
||||
|
||||
SendPredictedMessage(new GasVolumePumpChangeTransferRateMessage(rate));
|
||||
SendMessage(new GasVolumePumpChangeTransferRateMessage(rate));
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
/// <summary>
|
||||
/// Update the UI state based on server-sent info
|
||||
/// </summary>
|
||||
/// <param name="state"></param>
|
||||
protected override void UpdateState(BoundUserInterfaceState state)
|
||||
{
|
||||
base.Update();
|
||||
|
||||
if (_window is null || !EntMan.TryGetComponent(Owner, out GasVolumePumpComponent? pump))
|
||||
base.UpdateState(state);
|
||||
if (_window == null || state is not GasVolumePumpBoundUserInterfaceState cast)
|
||||
return;
|
||||
|
||||
_window.Title = Identity.Name(Owner, EntMan);
|
||||
_window.SetPumpStatus(pump.Enabled);
|
||||
_window.SetTransferRate(pump.TransferRate);
|
||||
_window.Title = cast.PumpLabel;
|
||||
_window.SetPumpStatus(cast.Enabled);
|
||||
_window.SetTransferRate(cast.TransferRate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<controls:FancyWindow xmlns="https://spacestation14.io"
|
||||
<DefaultWindow xmlns="https://spacestation14.io"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
||||
MinSize="200 120" Title="Volume Pump">
|
||||
<BoxContainer Orientation="Vertical" Margin="5 5 5 5" SeparationOverride="10">
|
||||
<BoxContainer Orientation="Horizontal" HorizontalExpand="True">
|
||||
@@ -20,4 +19,4 @@
|
||||
<Button Name="SetTransferRateButton" Text="{Loc comp-gas-pump-ui-pump-set-rate}" HorizontalAlignment="Right" Disabled="True"/>
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
</controls:FancyWindow>
|
||||
</DefaultWindow>
|
||||
|
||||
@@ -2,7 +2,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using Content.Client.Atmos.EntitySystems;
|
||||
using Content.Client.UserInterface.Controls;
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Atmos.Prototypes;
|
||||
using Robust.Client.AutoGenerated;
|
||||
@@ -17,7 +16,7 @@ namespace Content.Client.Atmos.UI
|
||||
/// Client-side UI used to control a gas volume pump.
|
||||
/// </summary>
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class GasVolumePumpWindow : FancyWindow
|
||||
public sealed partial class GasVolumePumpWindow : DefaultWindow
|
||||
{
|
||||
public bool PumpStatus = true;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<DefaultWindow xmlns="https://spacestation14.io"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
MinSize="280 160" Title="{Loc comp-space-heater-ui-title}">
|
||||
MinSize="280 160" Title="Temperature Control Unit">
|
||||
|
||||
<BoxContainer Name="VboxContainer" Orientation="Vertical" Margin="5 5 5 5" SeparationOverride="10">
|
||||
|
||||
|
||||
@@ -2,37 +2,35 @@ using Robust.Client.GameObjects;
|
||||
using Content.Shared.Atmos.Visuals;
|
||||
using Content.Client.Power;
|
||||
|
||||
namespace Content.Client.Atmos.Visualizers;
|
||||
|
||||
/// <summary>
|
||||
/// Controls client-side visuals for portable scrubbers.
|
||||
/// </summary>
|
||||
public sealed class PortableScrubberSystem : VisualizerSystem<PortableScrubberVisualsComponent>
|
||||
namespace Content.Client.Atmos.Visualizers
|
||||
{
|
||||
[Dependency] private readonly SpriteSystem _sprite = default!;
|
||||
|
||||
protected override void OnAppearanceChange(EntityUid uid, PortableScrubberVisualsComponent component, ref AppearanceChangeEvent args)
|
||||
/// <summary>
|
||||
/// Controls client-side visuals for portable scrubbers.
|
||||
/// </summary>
|
||||
public sealed class PortableScrubberSystem : VisualizerSystem<PortableScrubberVisualsComponent>
|
||||
{
|
||||
if (args.Sprite == null)
|
||||
return;
|
||||
|
||||
if (AppearanceSystem.TryGetData<bool>(uid, PortableScrubberVisuals.IsFull, out var isFull, args.Component)
|
||||
&& AppearanceSystem.TryGetData<bool>(uid, PortableScrubberVisuals.IsRunning, out var isRunning, args.Component))
|
||||
protected override void OnAppearanceChange(EntityUid uid, PortableScrubberVisualsComponent component, ref AppearanceChangeEvent args)
|
||||
{
|
||||
var runningState = isRunning ? component.RunningState : component.IdleState;
|
||||
_sprite.LayerSetRsiState((uid, args.Sprite), PortableScrubberVisualLayers.IsRunning, runningState);
|
||||
if (args.Sprite == null)
|
||||
return;
|
||||
|
||||
var fullState = isFull ? component.FullState : component.ReadyState;
|
||||
_sprite.LayerSetRsiState((uid, args.Sprite), PowerDeviceVisualLayers.Powered, fullState);
|
||||
}
|
||||
if (AppearanceSystem.TryGetData<bool>(uid, PortableScrubberVisuals.IsFull, out var isFull, args.Component)
|
||||
&& AppearanceSystem.TryGetData<bool>(uid, PortableScrubberVisuals.IsRunning, out var isRunning, args.Component))
|
||||
{
|
||||
var runningState = isRunning ? component.RunningState : component.IdleState;
|
||||
args.Sprite.LayerSetState(PortableScrubberVisualLayers.IsRunning, runningState);
|
||||
|
||||
if (AppearanceSystem.TryGetData<bool>(uid, PortableScrubberVisuals.IsDraining, out var isDraining, args.Component))
|
||||
{
|
||||
_sprite.LayerSetVisible((uid, args.Sprite), PortableScrubberVisualLayers.IsDraining, isDraining);
|
||||
var fullState = isFull ? component.FullState : component.ReadyState;
|
||||
args.Sprite.LayerSetState(PowerDeviceVisualLayers.Powered, fullState);
|
||||
}
|
||||
|
||||
if (AppearanceSystem.TryGetData<bool>(uid, PortableScrubberVisuals.IsDraining, out var isDraining, args.Component))
|
||||
{
|
||||
args.Sprite.LayerSetVisible(PortableScrubberVisualLayers.IsDraining, isDraining);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum PortableScrubberVisualLayers : byte
|
||||
{
|
||||
IsRunning,
|
||||
|
||||
@@ -66,7 +66,7 @@ public sealed class ClientGlobalSoundSystem : SharedGlobalSoundSystem
|
||||
{
|
||||
if(!_adminAudioEnabled) return;
|
||||
|
||||
var stream = _audio.PlayGlobal(soundEvent.Specifier, Filter.Local(), false, soundEvent.AudioParams);
|
||||
var stream = _audio.PlayGlobal(soundEvent.Filename, Filter.Local(), false, soundEvent.AudioParams);
|
||||
_adminAudio.Add(stream?.Entity);
|
||||
}
|
||||
|
||||
@@ -75,13 +75,13 @@ public sealed class ClientGlobalSoundSystem : SharedGlobalSoundSystem
|
||||
// Either the cvar is disabled or it's already playing
|
||||
if(!_eventAudioEnabled || _eventAudio.ContainsKey(soundEvent.Type)) return;
|
||||
|
||||
var stream = _audio.PlayGlobal(soundEvent.Specifier, Filter.Local(), false, soundEvent.AudioParams);
|
||||
var stream = _audio.PlayGlobal(soundEvent.Filename, Filter.Local(), false, soundEvent.AudioParams);
|
||||
_eventAudio.Add(soundEvent.Type, stream?.Entity);
|
||||
}
|
||||
|
||||
private void PlayGameSound(GameGlobalSoundEvent soundEvent)
|
||||
{
|
||||
_audio.PlayGlobal(soundEvent.Specifier, Filter.Local(), false, soundEvent.AudioParams);
|
||||
_audio.PlayGlobal(soundEvent.Filename, Filter.Local(), false, soundEvent.AudioParams);
|
||||
}
|
||||
|
||||
private void StopStationEventMusic(StopStationEventMusic soundEvent)
|
||||
|
||||
@@ -43,11 +43,14 @@ public sealed partial class ContentAudioSystem
|
||||
|
||||
private void CP14UpdateAmbientLoops()
|
||||
{
|
||||
return; //DISABLED UNTIL CLIENT ERROR SPAM FIXED
|
||||
|
||||
if (_timing.CurTime <= _nextUpdateTime)
|
||||
return;
|
||||
|
||||
_nextUpdateTime = _timing.CurTime + _updateFrequency;
|
||||
|
||||
|
||||
if (_state.CurrentState is not GameplayState)
|
||||
return;
|
||||
|
||||
|
||||
@@ -218,7 +218,7 @@ public sealed partial class ContentAudioSystem
|
||||
return;
|
||||
|
||||
var file = _gameTicker.RestartSound;
|
||||
if (ResolvedSoundSpecifier.IsNullOrEmpty(file))
|
||||
if (string.IsNullOrEmpty(file))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ public sealed class JukeboxSystem : SharedJukeboxSystem
|
||||
[Dependency] private readonly AnimationPlayerSystem _animationPlayer = default!;
|
||||
[Dependency] private readonly SharedAppearanceSystem _appearanceSystem = default!;
|
||||
[Dependency] private readonly SharedUserInterfaceSystem _uiSystem = default!;
|
||||
[Dependency] private readonly SpriteSystem _sprite = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -65,7 +64,7 @@ public sealed class JukeboxSystem : SharedJukeboxSystem
|
||||
visualState = JukeboxVisualState.On;
|
||||
}
|
||||
|
||||
UpdateAppearance((uid, sprite), visualState, component);
|
||||
UpdateAppearance(uid, visualState, component, sprite);
|
||||
}
|
||||
|
||||
private void OnAppearanceChange(EntityUid uid, JukeboxComponent component, ref AppearanceChangeEvent args)
|
||||
@@ -79,25 +78,25 @@ public sealed class JukeboxSystem : SharedJukeboxSystem
|
||||
visualState = JukeboxVisualState.On;
|
||||
}
|
||||
|
||||
UpdateAppearance((uid, args.Sprite), visualState, component);
|
||||
UpdateAppearance(uid, visualState, component, args.Sprite);
|
||||
}
|
||||
|
||||
private void UpdateAppearance(Entity<SpriteComponent> entity, JukeboxVisualState visualState, JukeboxComponent component)
|
||||
private void UpdateAppearance(EntityUid uid, JukeboxVisualState visualState, JukeboxComponent component, SpriteComponent sprite)
|
||||
{
|
||||
SetLayerState(JukeboxVisualLayers.Base, component.OffState, entity);
|
||||
SetLayerState(JukeboxVisualLayers.Base, component.OffState, sprite);
|
||||
|
||||
switch (visualState)
|
||||
{
|
||||
case JukeboxVisualState.On:
|
||||
SetLayerState(JukeboxVisualLayers.Base, component.OnState, entity);
|
||||
SetLayerState(JukeboxVisualLayers.Base, component.OnState, sprite);
|
||||
break;
|
||||
|
||||
case JukeboxVisualState.Off:
|
||||
SetLayerState(JukeboxVisualLayers.Base, component.OffState, entity);
|
||||
SetLayerState(JukeboxVisualLayers.Base, component.OffState, sprite);
|
||||
break;
|
||||
|
||||
case JukeboxVisualState.Select:
|
||||
PlayAnimation(entity.Owner, JukeboxVisualLayers.Base, component.SelectState, 1.0f, entity);
|
||||
PlayAnimation(uid, JukeboxVisualLayers.Base, component.SelectState, 1.0f, sprite);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -110,7 +109,7 @@ public sealed class JukeboxSystem : SharedJukeboxSystem
|
||||
if (!_animationPlayer.HasRunningAnimation(uid, state))
|
||||
{
|
||||
var animation = GetAnimation(layer, state, animationTime);
|
||||
_sprite.LayerSetVisible((uid, sprite), layer, true);
|
||||
sprite.LayerSetVisible(layer, true);
|
||||
_animationPlayer.Play(uid, animation, state);
|
||||
}
|
||||
}
|
||||
@@ -134,13 +133,13 @@ public sealed class JukeboxSystem : SharedJukeboxSystem
|
||||
};
|
||||
}
|
||||
|
||||
private void SetLayerState(JukeboxVisualLayers layer, string? state, Entity<SpriteComponent> sprite)
|
||||
private void SetLayerState(JukeboxVisualLayers layer, string? state, SpriteComponent sprite)
|
||||
{
|
||||
if (string.IsNullOrEmpty(state))
|
||||
return;
|
||||
|
||||
_sprite.LayerSetVisible(sprite.AsNullable(), layer, true);
|
||||
_sprite.LayerSetAutoAnimated(sprite.AsNullable(), layer, true);
|
||||
_sprite.LayerSetRsiState(sprite.AsNullable(), layer, state);
|
||||
sprite.LayerSetVisible(layer, true);
|
||||
sprite.LayerSetAutoAnimated(layer, true);
|
||||
sprite.LayerSetState(layer, state);
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user