diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 1adc0b803df..4e1a86d79eb 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,65 +1,7 @@ # Last match in file takes precedence. -# 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/ @Chief-Engineer +# Ping for all PRs +* @Morb0 -# Moony's Gargantuan List Of Things She Cares About, or MGLOTSCA for short. -# You need to add your name to these entries, not make a new one, if you care about them. -/Content.*/Toolshed/ @moonheart08 -**/Toolshed/** @moonheart08 -*Command.cs @moonheart08 -/Content.*/Administration/ @moonheart08 @DrSmugleaf @Chief-Engineer -/Content.*/Station/ @moonheart08 -/Content.*/Maps/ @moonheart08 -/Content.*/GameTicking/ @moonheart08 @EmoGarbage404 -/Resources/ServerInfo/ @moonheart08 @Chief-Engineer -/Resources/ServerInfo/Guidebook/ @moonheart08 @EmoGarbage404 -/Resources/engineCommandPerms.yml @moonheart08 @Chief-Engineer -/Resources/clientCommandPerms.yml @moonheart08 @Chief-Engineer - -/Resources/Prototypes/Maps/ @Emisse - -/Resources/Prototypes/Body/ @DrSmugleaf # suffering -/Resources/Prototypes/Entities/Mobs/Player/ @DrSmugleaf -/Resources/Prototypes/Entities/Mobs/Species/ @DrSmugleaf -/Content.*/Body/ @DrSmugleaf -/Content.YAMLLinter @DrSmugleaf - -/Content.*/Verbs/ @ElectroJr -/Content.Client/ContextMenu/ @ElectroJr -/Content.Shared/Damage/ @ElectroJr @DrSmugleaf -/Content.Shared/Containers/ItemSlot/ @ElectroJr -/Content.*/PowerCell/ @ElectroJr -/Content.*/Doors/ @ElectroJr -/Content.*/Interaction/ @ElectroJr -/Content.*/Hands/ @ElectroJr -/Content.*/Actions/ @ElectroJr -/Content.*/Explosion/ @ElectroJr - -/Content.*/Anomaly/ @EmoGarbage404 -/Content.*/Lathe/ @EmoGarbage404 -/Content.*/Materials/ @EmoGarbage404 -/Content.*/Mech/ @EmoGarbage404 -/Content.*/Research/ @EmoGarbage404 -/Content.*/Stack/ @EmoGarbage404 -/Content.*/Xenoarchaeology/ @EmoGarbage404 -/Content.*/Zombies/ @EmoGarbage404 -/Resources/Prototypes/Entities/Structures/Specific/anomalies.yml @EmoGarbage404 -/Resources/Prototypes/Research/ @EmoGarbage404 - -/Content.*/Forensics/ @ficcialfaint - -# SKREEEE -/Content.*.Database/ @PJB3005 @DrSmugleaf -/Content.Shared.Database/Log*.cs @PJB3005 @DrSmugleaf @Chief-Engineer -/Pow3r/ @PJB3005 -/Content.Server/Power/Pow3r/ @PJB3005 - -# notafet -/Content.*/Atmos/ @Partmedia -/Content.*/Botany/ @Partmedia - -#Jezi -/Content.*/Medical @Jezithyr -/Content.*/Body @Jezithyr +# Ping for all PRs that include translations/editing fluent strings +*.ftl @ficcialfaint diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 00000000000..f3666ae94fc --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,29 @@ +name: "Сообщить о проблеме" +description: "Если что-то работает не так, как ожидалось." +labels: ["triage"] +body: + - type: textarea + id: description + validations: + required: true + attributes: + label: "Описание" + description: "Опишите проблему как можно подробнее" + + - type: textarea + id: reproduction + attributes: + label: "Шаги воспроизведения" + description: "Если приемлемо, опишите шаги для воспроизведения проблемы" + placeholder: | + 1. Открыть интерфейс консоли + 2. Нажать кнопку "Старт" + 3. Получить ошибку... + + - type: textarea + id: screenshots + attributes: + label: "Скриншоты" + description: | + Если приемлемо, добавьте скриншоты, чтобы помочь объяснить вашу проблему + **Подсказка**: Вы можете прикрепить изображения щелкнув по области ниже, чтобы выделить её, а затем перетащив в нее файлы diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 09c9e76b193..f00e08f8d2e 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,7 +1,7 @@ contact_links: - - name: Report a Security Vulnerability - url: https://github.com/space-wizards/space-station-14/blob/master/SECURITY.md - about: Please report security vulnerabilities privately so we can fix them before they are publicly disclosed. - - name: Request a Feature - url: https://discord.gg/rGvu9hKffJ - about: Submit feature requests on our Discord server (https://discord.gg/rGvu9hKffJ). + - name: Предложение + url: https://discord.station14.ru + about: Свои предложения можете оставлять в соответствующем канале Discord. + - name: Сообщить об уязвимости + url: https://discord.station14.ru + about: Пожалуйста, сообщайте о серьезных эксплойтах и уязвимостях безопасности Morty#7384 (369476049836310528) в Discord. diff --git a/.github/ISSUE_TEMPLATE/issue_report.md b/.github/ISSUE_TEMPLATE/issue_report.md deleted file mode 100644 index 9bc805b74e1..00000000000 --- a/.github/ISSUE_TEMPLATE/issue_report.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -name: Report an Issue -about: "..." -title: '' -labels: '' -assignees: '' - ---- - -## Description - - -**Reproduction** - - -**Screenshots** - - -**Additional context** - diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index a397604185a..e56d2bfceda 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,43 +1,36 @@ - - + -## About the PR - +## Описание PR + -## Why / Balance - +**Медиа** + -## Technical details - +**Проверки** + +- [ ] PR полностью завершён и мне не нужна помощь чтобы его закончить. +- [ ] Я внимательно просмотрел все свои изменения и багов в них не нашёл. +- [ ] Я запускал локальный сервер со своими изменениями и всё протестировал. +- [ ] Я добавил скриншот/видео демонстрации PR в игре, **или** этот PR этого не требует. -## Media - +В журнал изменений следует помещать только то, что действительно важно игрокам. -- [ ] I have added screenshots/videos to this PR showcasing its changes ingame, **or** this PR does not require an ingame showcase +В списке изменений тип значка не является часть предложения, поэтому явно указывайте - Добавлен, Удалён, Изменён. +плохо: - add: Новый инструмент для инженеров +хорошо: - add: Добавлен новый инструмент для инженеров -## Breaking changes - +Вы можете указать своё имя после символа :cl: именно оно будет отображаться в журнале изменений (иначе будет использоваться ваше имя на GitHub) +Например: :cl: Ian -**Changelog** - - +- add: Добавлено веселье! +- remove: Убрано веселье! +- tweak: Изменено веселье! +- fix: Исправлено веселье! diff --git a/.github/labeler.yml b/.github/labeler.yml index b088f229434..e54e8922146 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -8,5 +8,8 @@ "Changes: UI": - '**/*.xaml*' +"Changes: Localization": +- 'Resources/Locale/**/*.ftl' + "No C#": - all: ["!**/*.cs"] diff --git a/.github/workflows/build-test-debug.yml b/.github/workflows/build-test-debug.yml index 9abd4fbe17e..54b11ee98ad 100644 --- a/.github/workflows/build-test-debug.yml +++ b/.github/workflows/build-test-debug.yml @@ -10,7 +10,7 @@ on: jobs: build: - if: github.actor != 'PJBot' && github.event.pull_request.draft == false + if: github.actor != 'IanComradeBot' && github.event.pull_request.draft == false strategy: matrix: os: [ubuntu-latest] diff --git a/.github/workflows/conflict-labeler.yml b/.github/workflows/conflict-labeler.yml index a78716bde68..951042d087b 100644 --- a/.github/workflows/conflict-labeler.yml +++ b/.github/workflows/conflict-labeler.yml @@ -8,7 +8,7 @@ on: jobs: Label: - if: github.actor != 'PJBot' + if: github.actor != 'IanComradeBot' runs-on: ubuntu-latest steps: - name: Check for Merge Conflicts diff --git a/.github/workflows/labeler-approve.yml b/.github/workflows/labeler-approve.yml new file mode 100644 index 00000000000..15b092aa3b3 --- /dev/null +++ b/.github/workflows/labeler-approve.yml @@ -0,0 +1,18 @@ +name: "Labels: Approve" + +on: + pull_request_review: + types: [submitted] + +jobs: + remove_label: + permissions: + pull-requests: write + if: github.event.review.state == 'approved' + runs-on: ubuntu-latest + steps: + - uses: actions-ecosystem/action-remove-labels@v1 + with: + labels: | + Status: Needs Review + Status: Awaiting Changes diff --git a/.github/workflows/labeler-changes.yml b/.github/workflows/labeler-changes.yml new file mode 100644 index 00000000000..e7d8fc45e16 --- /dev/null +++ b/.github/workflows/labeler-changes.yml @@ -0,0 +1,19 @@ +name: "Labels: Changes" + +on: + pull_request_review: + types: [submitted] + +jobs: + update_label: + permissions: + pull-requests: write + if: github.event.review.state == 'changes_requested' + runs-on: ubuntu-latest + steps: + - uses: actions-ecosystem/action-add-labels@v1 + with: + labels: "Status: Awaiting Changes" + - uses: actions-ecosystem/action-remove-labels@v1 + with: + labels: "Status: Needs Review" diff --git a/.github/workflows/labeler-pr.yml b/.github/workflows/labeler-pr.yml index 711eb0ccac0..31b860c3c36 100644 --- a/.github/workflows/labeler-pr.yml +++ b/.github/workflows/labeler-pr.yml @@ -5,7 +5,7 @@ on: jobs: labeler: - if: github.actor != 'PJBot' + if: github.actor != 'IanComradeBot' runs-on: ubuntu-latest steps: - uses: actions/labeler@v3 diff --git a/.github/workflows/publish-publish.yml b/.github/workflows/publish-publish.yml new file mode 100644 index 00000000000..9f4efd87dfe --- /dev/null +++ b/.github/workflows/publish-publish.yml @@ -0,0 +1,74 @@ +name: Publish Public + +#concurrency: +# group: publish + +on: + workflow_dispatch: + schedule: + - cron: '0 1 * * *' + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Check configuration + env: + PUBLIC_PATH: ${{ secrets.BUILDS_PUBLIC_PATH }} + if: ${{ env.PUBLIC_PATH == '' }} + uses: andymckay/cancel-action@0.3 + + - uses: actions/checkout@v3.6.0 + with: + submodules: 'recursive' + + - name: Setup .NET Core + uses: actions/setup-dotnet@v3.2.0 + with: + dotnet-version: 7.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: Update Build Info + env: + FORK_ID: ${{ vars.FORK_ID }} + run: Tools/gen_build_info.py + + - name: Shuffle files around + run: | + mkdir "release/${{ github.sha }}" + mv release/SS14.Server*.zip "release/${{ github.sha }}" + + - name: Upload files to mothership + uses: burnett01/rsync-deployments@5.2 + with: + switches: -avzr --ignore-existing + path: "release/${{ github.sha }}" + remote_path: ${{ secrets.BUILDS_PUBLIC_PATH }} + remote_host: ${{ secrets.BUILDS_HOST }} + remote_user: ${{ secrets.BUILDS_USERNAME }} + remote_key: ${{ secrets.BUILDS_SSH_KEY }} + + - name: Generate public HTML + uses: appleboy/ssh-action@master + with: + host: ${{ secrets.BUILDS_HOST }} + username: ${{ secrets.BUILDS_USERNAME }} + key: ${{ secrets.BUILDS_SSH_KEY }} + script: node ~/scripts/generate_html_page.js -fork ${{ vars.FORK_ID_PUBLIC }} -id ${{ github.sha }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 82837638390..78b05f9c87e 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -6,19 +6,38 @@ concurrency: on: workflow_dispatch: schedule: - - cron: '0 10 * * *' + - cron: '0 6 * * *' jobs: build: runs-on: ubuntu-latest steps: - - name: Install dependencies - run: sudo apt-get install -y python3-paramiko +# - name: Install dependencies +# run: sudo apt-get install -y python3-paramiko - uses: actions/checkout@v3.6.0 with: submodules: 'recursive' + + # Corvax-Secrets-Start + - name: Setup secrets + env: + SSH_KEY: ${{ secrets.SECRETS_PRIVATE_KEY }} + if: ${{ env.SSH_KEY != '' }} + run: | + mkdir ~/.ssh + echo "${{ secrets.SECRETS_PRIVATE_KEY }}" > ~/.ssh/id_rsa + chmod 600 ~/.ssh/id_rsa + echo "HOST *" > ~/.ssh/config + echo "StrictHostKeyChecking no" >> ~/.ssh/config + git -c submodule.Secrets.update=checkout submodule update --init + cp -R Secrets/Resources/Prototypes Resources/Prototypes/CorvaxSecrets + cp -R Secrets/Resources/ServerPrototypes Resources/Prototypes/CorvaxSecretsServer + cp -R Secrets/Resources/Locale Resources/Locale/ru-RU/corvax-secrets + cp -R Secrets/Resources/Textures Resources/Textures/CorvaxSecrets + # Corvax-Secrets-End + - name: Setup .NET Core uses: actions/setup-dotnet@v3.2.0 with: @@ -42,6 +61,8 @@ jobs: run: dotnet run --project Content.Packaging client --no-wipe-release - name: Update Build Info + env: + FORK_ID: ${{ vars.FORK_ID }} run: Tools/gen_build_info.py - name: Shuffle files around @@ -49,31 +70,32 @@ jobs: mkdir "release/${{ github.sha }}" mv release/*.zip "release/${{ github.sha }}" - - name: Upload files to centcomm - uses: appleboy/scp-action@master + - name: Upload files to mothership + uses: burnett01/rsync-deployments@5.2 with: - host: centcomm.spacestation14.io - username: wizards-build-push - key: ${{ secrets.CENTCOMM_WIZARDS_BUILDS_PUSH_KEY }} - source: "release/${{ github.sha }}" - target: "/home/wizards-build-push/builds_dir/builds/" - strip_components: 1 + switches: -avzr --ignore-existing + path: "release/${{ github.sha }}" + remote_path: ${{ secrets.BUILDS_PATH }} + remote_host: ${{ secrets.BUILDS_HOST }} + remote_user: ${{ secrets.BUILDS_USERNAME }} + remote_key: ${{ secrets.BUILDS_SSH_KEY }} - name: Update manifest JSON uses: appleboy/ssh-action@master with: - host: centcomm.spacestation14.io - username: wizards-build-push - key: ${{ secrets.CENTCOMM_WIZARDS_BUILDS_PUSH_KEY }} - script: /home/wizards-build-push/push.ps1 ${{ github.sha }} - - - name: Publish changelog (Discord) - 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) - run: Tools/actions_changelog_rss.py - env: - CHANGELOG_RSS_KEY: ${{ secrets.CHANGELOG_RSS_KEY }} + host: ${{ secrets.BUILDS_HOST }} + username: ${{ secrets.BUILDS_USERNAME }} + key: ${{ secrets.BUILDS_SSH_KEY }} + script: node ~/scripts/push_to_manifest.js -fork ${{ vars.FORK_ID }} -id ${{ github.sha }} + +# - name: Publish changelog (Discord) +# run: Tools/actions_changelogs_since_last_run.py +# env: +# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} +# DISCORD_WEBHOOK_URL: ${{ secrets.CHANGELOG_DISCORD_WEBHOOK }} +# TRANSLATION_API_URL: ${{ secrets.CHANGELOG_TRANSLATION_API_URL }} +# +# - name: Publish changelog (RSS) +# run: Tools/actions_changelog_rss.py +# env: +# CHANGELOG_RSS_KEY: ${{ secrets.CHANGELOG_RSS_KEY }} diff --git a/.github/workflows/test-packaging.yml b/.github/workflows/test-packaging.yml index b22f307de57..859c04ce8cc 100644 --- a/.github/workflows/test-packaging.yml +++ b/.github/workflows/test-packaging.yml @@ -29,7 +29,7 @@ on: jobs: build: name: Test Packaging - if: github.actor != 'PJBot' && github.event.pull_request.draft == false + if: github.actor != 'IanComradeBot' && github.event.pull_request.draft == false runs-on: ubuntu-latest steps: @@ -48,6 +48,20 @@ jobs: cd RobustToolbox/ git submodule update --init --recursive + # Corvax-Secrets-Start + - name: Setup secrets + env: + SSH_KEY: ${{ secrets.SECRETS_PRIVATE_KEY }} + if: ${{ env.SSH_KEY != '' }} + run: | + mkdir ~/.ssh + echo "${{ secrets.SECRETS_PRIVATE_KEY }}" > ~/.ssh/id_rsa + chmod 600 ~/.ssh/id_rsa + echo "HOST *" > ~/.ssh/config + echo "StrictHostKeyChecking no" >> ~/.ssh/config + git -c submodule.Secrets.update=checkout submodule update --init + # Corvax-Secrets-End + - name: Setup .NET Core uses: actions/setup-dotnet@v3.2.0 with: @@ -66,6 +80,8 @@ jobs: run: dotnet run --project Content.Packaging client --no-wipe-release - name: Update Build Info + env: + FORK_ID: ${{ vars.FORK_ID }} run: Tools/gen_build_info.py - name: Shuffle files around diff --git a/.github/workflows/update-wiki.yml b/.github/workflows/update-wiki.yml new file mode 100644 index 00000000000..b353d5bfe64 --- /dev/null +++ b/.github/workflows/update-wiki.yml @@ -0,0 +1,91 @@ +name: Update Wiki + +on: + workflow_dispatch: + push: + branches: [ master, jsondump ] + paths: + - '.github/workflows/update-wiki.yml' + - 'Content.Shared/Chemistry/**.cs' + - 'Content.Server/Chemistry/**.cs' + - 'Content.Server/GuideGenerator/**.cs' + - 'Resources/Prototypes/Reagents/**.yml' + - 'Resources/Prototypes/Chemistry/**.yml' + - 'Resources/Prototypes/Recipes/Reactions/**.yml' + - 'RobustToolbox/' + +jobs: + update-wiki: + name: Build and Publish JSON blobs to wiki + runs-on: ubuntu-latest + + steps: + - name: Checkout Master + uses: actions/checkout@v3.6.0 + + - name: Setup Submodule + run: | + git submodule update --init --recursive + + - name: Pull Engine Updates + uses: space-wizards/submodule-dependency@v0.1.5 + + - name: Update Engine Submodules + run: | + cd RobustToolbox/ + git submodule update --init --recursive + + - name: Setup .NET Core + uses: actions/setup-dotnet@v3.2.0 + with: + dotnet-version: 7.0.x + + - name: Install Dependencies + run: dotnet restore + + - name: Build Project + run: dotnet build --configuration Release --no-restore /p:WarningsAsErrors=nullable /m + + - name: Generate JSON blobs for prototypes + run: dotnet ./bin/Content.Server/Content.Server.dll --cvar autogen.destination_file=prototypes.json + continue-on-error: true + + - name: Upload chem_prototypes.json to wiki + uses: jtmullen/mediawiki-edit-action@v0.1.1 + with: + wiki_text_file: ./bin/Content.Server/data/chem_prototypes.json + edit_summary: Update chem_prototypes.json via GitHub Actions + page_name: "${{ secrets.WIKI_PAGE_ROOT }}/chem_prototypes.json" + api_url: ${{ secrets.WIKI_ROOT_URL }}/api.php + username: ${{ secrets.WIKI_BOT_USER }} + password: ${{ secrets.WIKI_BOT_PASS }} + + - name: Upload react_prototypes.json to wiki + uses: jtmullen/mediawiki-edit-action@v0.1.1 + with: + wiki_text_file: ./bin/Content.Server/data/react_prototypes.json + edit_summary: Update react_prototypes.json via GitHub Actions + page_name: "${{ secrets.WIKI_PAGE_ROOT }}/react_prototypes.json" + api_url: ${{ secrets.WIKI_ROOT_URL }}/api.php + username: ${{ secrets.WIKI_BOT_USER }} + password: ${{ secrets.WIKI_BOT_PASS }} + + - name: Upload entity_prototypes.json to wiki + uses: jtmullen/mediawiki-edit-action@v0.1.1 + with: + wiki_text_file: ./bin/Content.Server/data/entity_prototypes.json + edit_summary: Update entity_prototypes.json via GitHub Actions + page_name: "${{ secrets.WIKI_PAGE_ROOT }}/entity_prototypes.json" + api_url: ${{ secrets.WIKI_ROOT_URL }}/api.php + username: ${{ secrets.WIKI_BOT_USER }} + password: ${{ secrets.WIKI_BOT_PASS }} + + - name: Upload mealrecipes_prototypes.json to wiki + uses: jtmullen/mediawiki-edit-action@v0.1.1 + with: + wiki_text_file: ./bin/Content.Server/data/mealrecipes_prototypes.json + edit_summary: Update mealrecipes_prototypes.json via GitHub Actions + page_name: "${{ secrets.WIKI_PAGE_ROOT }}/mealrecipes_prototypes.json" + api_url: ${{ secrets.WIKI_ROOT_URL }}/api.php + username: ${{ secrets.WIKI_BOT_USER }} + password: ${{ secrets.WIKI_BOT_PASS }} diff --git a/.github/workflows/validate-rgas.yml b/.github/workflows/validate-rgas.yml index 2c4bb40fdf3..1132c01960d 100644 --- a/.github/workflows/validate-rgas.yml +++ b/.github/workflows/validate-rgas.yml @@ -9,12 +9,25 @@ on: jobs: yaml-schema-validation: name: YAML RGA schema validator - if: github.actor != 'PJBot' && github.event.pull_request.draft == false + if: github.actor != 'IanComradeBot' && github.event.pull_request.draft == false runs-on: ubuntu-latest steps: - uses: actions/checkout@v3.6.0 - name: Setup Submodule run: git submodule update --init + # Corvax-Secrets-Start + - name: Setup secrets + env: + SSH_KEY: ${{ secrets.SECRETS_PRIVATE_KEY }} + if: ${{ env.SSH_KEY != '' }} + run: | + mkdir ~/.ssh + echo "${{ secrets.SECRETS_PRIVATE_KEY }}" > ~/.ssh/id_rsa + chmod 600 ~/.ssh/id_rsa + echo "HOST *" > ~/.ssh/config + echo "StrictHostKeyChecking no" >> ~/.ssh/config + git -c submodule.Secrets.update=checkout submodule update --init + # Corvax-Secrets-End - name: Pull engine updates uses: space-wizards/submodule-dependency@v0.1.5 - uses: PaulRitter/yaml-schema-validator@v1 diff --git a/.github/workflows/validate-rsis.yml b/.github/workflows/validate-rsis.yml index b76df28e6af..be37678b5a0 100644 --- a/.github/workflows/validate-rsis.yml +++ b/.github/workflows/validate-rsis.yml @@ -16,6 +16,19 @@ jobs: - uses: actions/checkout@v3.6.0 - name: Setup Submodule run: git submodule update --init + # Corvax-Secrets-Start + - name: Setup secrets + env: + SSH_KEY: ${{ secrets.SECRETS_PRIVATE_KEY }} + if: ${{ env.SSH_KEY != '' }} + run: | + mkdir ~/.ssh + echo "${{ secrets.SECRETS_PRIVATE_KEY }}" > ~/.ssh/id_rsa + chmod 600 ~/.ssh/id_rsa + echo "HOST *" > ~/.ssh/config + echo "StrictHostKeyChecking no" >> ~/.ssh/config + git -c submodule.Secrets.update=checkout submodule update --init + # Corvax-Secrets-End - name: Pull engine updates uses: space-wizards/submodule-dependency@v0.1.5 - name: Install Python dependencies diff --git a/.github/workflows/validate_mapfiles.yml b/.github/workflows/validate_mapfiles.yml index fb11e1a4697..bb6eeaf411f 100644 --- a/.github/workflows/validate_mapfiles.yml +++ b/.github/workflows/validate_mapfiles.yml @@ -9,12 +9,25 @@ on: jobs: yaml-schema-validation: name: YAML map schema validator - if: github.actor != 'PJBot' && github.event.pull_request.draft == false + if: github.actor != 'IanComradeBot' && github.event.pull_request.draft == false runs-on: ubuntu-latest steps: - uses: actions/checkout@v3.6.0 - name: Setup Submodule run: git submodule update --init + # Corvax-Secrets-Start + - name: Setup secrets + env: + SSH_KEY: ${{ secrets.SECRETS_PRIVATE_KEY }} + if: ${{ env.SSH_KEY != '' }} + run: | + mkdir ~/.ssh + echo "${{ secrets.SECRETS_PRIVATE_KEY }}" > ~/.ssh/id_rsa + chmod 600 ~/.ssh/id_rsa + echo "HOST *" > ~/.ssh/config + echo "StrictHostKeyChecking no" >> ~/.ssh/config + git -c submodule.Secrets.update=checkout submodule update --init + # Corvax-Secrets-End - name: Pull engine updates uses: space-wizards/submodule-dependency@v0.1.5 - uses: PaulRitter/yaml-schema-validator@v1 diff --git a/.github/workflows/yaml-linter.yml b/.github/workflows/yaml-linter.yml index 254384acff0..8798c95e19a 100644 --- a/.github/workflows/yaml-linter.yml +++ b/.github/workflows/yaml-linter.yml @@ -10,7 +10,7 @@ on: jobs: build: name: YAML Linter - if: github.actor != 'PJBot' && github.event.pull_request.draft == false + if: github.actor != 'IanComradeBot' && github.event.pull_request.draft == false runs-on: ubuntu-latest steps: - uses: actions/checkout@v3.6.0 diff --git a/.gitignore b/.gitignore index 2dd5912047c..533060b4996 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,12 @@ # User-specific files (MonoDevelop/Xamarin Studio) *.userprefs +# Secret +Resources/Prototypes/CorvaxSecrets +Resources/Prototypes/CorvaxSecretsServer +Resources/Textures/CorvaxSecrets +Resources/Locale/ru-RU/corvax-secrets + # Build results [Dd]ebug/ [Dd]ebugPublic/ diff --git a/.gitmodules b/.gitmodules index 08e5dd6d0af..5ba1735ee8c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,9 @@ [submodule "RobustToolbox"] path = RobustToolbox url = https://github.com/space-wizards/RobustToolbox.git - branch = master \ No newline at end of file + branch = master +[submodule "Secrets"] + path = Secrets + url = git@github.com:corvax-project/secrets.git + branch = master + update = none diff --git a/CHANGES.md b/CHANGES.md new file mode 100644 index 00000000000..3b4340cd707 --- /dev/null +++ b/CHANGES.md @@ -0,0 +1,25 @@ +Main changes of this downstream: +- Russian translation + * Text in ftl files + * Accents + * Some sprites (direction signs) +- Merging downstream changelog file with upstream changelog +- Gender division files of last names for name generator +- More emotes for chat sanitization or cyrillic versions +- System of Discord round status notification +- Decreased interaction range to 1.4 + * Gravity generator fixture shape on top decreased +- Custom sprites + * Floor tiles + * Clothing + * Some objects +- Custom clothing + * Disco Elysium suits + * [BIG SHOT] glasses + * Special Operations Officer [Author] +- Custom tools for locale update and merging (/Tools/ss14_ru/) +- Station goals +- Sponsor rewards +- Increased role timers +- Custom roles + * Internal affairs agent diff --git a/Content.Client/Administration/UI/Tabs/AdminTab/AdminShuttleWindow.xaml b/Content.Client/Administration/UI/Tabs/AdminTab/AdminShuttleWindow.xaml index b26f0cfe445..974e9418461 100644 --- a/Content.Client/Administration/UI/Tabs/AdminTab/AdminShuttleWindow.xaml +++ b/Content.Client/Administration/UI/Tabs/AdminTab/AdminShuttleWindow.xaml @@ -7,8 +7,9 @@ + + - diff --git a/Content.Client/Chat/TypingIndicator/TypingIndicatorSystem.cs b/Content.Client/Chat/TypingIndicator/TypingIndicatorSystem.cs index 0eea36aa573..db1f3ae8d7f 100644 --- a/Content.Client/Chat/TypingIndicator/TypingIndicatorSystem.cs +++ b/Content.Client/Chat/TypingIndicator/TypingIndicatorSystem.cs @@ -16,6 +16,7 @@ public sealed class TypingIndicatorSystem : SharedTypingIndicatorSystem private readonly TimeSpan _typingTimeout = TimeSpan.FromSeconds(2); private TimeSpan _lastTextChange; private bool _isClientTyping; + private bool _isClientChatFocused; // Corvax-TypingIndicator public override void Initialize() { @@ -30,7 +31,10 @@ public void ClientChangedChatText() return; // client typed something - show typing indicator - ClientUpdateTyping(true); + // Corvax-TypingIndicator-Start + _isClientTyping = true; + ClientUpdateTyping(); + // Corvax-TypingIndicator-End _lastTextChange = _time.CurTime; } @@ -41,9 +45,26 @@ public void ClientSubmittedChatText() return; // client submitted text - hide typing indicator - ClientUpdateTyping(false); + // Corvax-TypingIndicator-Start + _isClientTyping = false; + _isClientChatFocused = false; + ClientUpdateTyping(); + // Corvax-TypingIndicator-End } + // Corvax-TypingIndicator-Start + public void ClientChangedChatFocus(bool isFocused) + { + // don't update it if player don't want to show typing + if (!_cfg.GetCVar(CCVars.ChatShowTypingIndicator)) + return; + + // client submitted text - hide typing indicator + _isClientChatFocused = isFocused; + ClientUpdateTyping(); + } + // Corvax-TypingIndicator-End + public override void Update(float frameTime) { base.Update(frameTime); @@ -55,23 +76,34 @@ public override void Update(float frameTime) if (dif > _typingTimeout) { // client didn't typed anything for a long time - hide indicator - ClientUpdateTyping(false); + // Corvax-TypingIndicator-Start + _isClientTyping = false; + ClientUpdateTyping(); + // Corvax-TypingIndicator-End } } } - private void ClientUpdateTyping(bool isClientTyping) + private void ClientUpdateTyping() // Corvax-TypingIndicator { - if (_isClientTyping == isClientTyping) - return; - _isClientTyping = isClientTyping; + // Corvax-TypingIndicator-Start + // if (_isClientTyping == isClientTyping) + // return; + // _isClientTyping = isClientTyping; + // Corvax-TypingIndicator-End // check if player controls any pawn if (_playerManager.LocalPlayer?.ControlledEntity == null) return; + // Corvax-TypingIndicator-Start + var state = TypingIndicatorState.None; + if (_isClientChatFocused) + state = _isClientTyping ? TypingIndicatorState.Typing : TypingIndicatorState.Idle; + // Corvax-TypingIndicator-End + // send a networked event to server - RaiseNetworkEvent(new TypingChangedEvent(isClientTyping)); + RaiseNetworkEvent(new TypingChangedEvent(state)); // Corvax-TypingIndicator } private void OnShowTypingChanged(bool showTyping) @@ -79,7 +111,10 @@ private void OnShowTypingChanged(bool showTyping) // hide typing indicator immediately if player don't want to show it anymore if (!showTyping) { - ClientUpdateTyping(false); + // Corvax-TypingIndicator-Start + _isClientTyping = false; + ClientUpdateTyping(); + // Corvax-TypingIndicator-End } } } diff --git a/Content.Client/Chat/TypingIndicator/TypingIndicatorVisualizerSystem.cs b/Content.Client/Chat/TypingIndicator/TypingIndicatorVisualizerSystem.cs index d04c9d661dd..182ddd74b64 100644 --- a/Content.Client/Chat/TypingIndicator/TypingIndicatorVisualizerSystem.cs +++ b/Content.Client/Chat/TypingIndicator/TypingIndicatorVisualizerSystem.cs @@ -20,7 +20,7 @@ protected override void OnAppearanceChange(EntityUid uid, TypingIndicatorCompone return; } - AppearanceSystem.TryGetData(uid, TypingIndicatorVisuals.IsTyping, out var isTyping, args.Component); + //AppearanceSystem.TryGetData(uid, TypingIndicatorVisuals.IsTyping, out var isTyping, args.Component); // Corvax-TypingIndicator var layerExists = args.Sprite.LayerMapTryGet(TypingIndicatorLayers.Base, out var layer); if (!layerExists) layer = args.Sprite.LayerMapReserveBlank(TypingIndicatorLayers.Base); @@ -29,6 +29,19 @@ protected override void OnAppearanceChange(EntityUid uid, TypingIndicatorCompone args.Sprite.LayerSetState(layer, proto.TypingState); args.Sprite.LayerSetShader(layer, proto.Shader); args.Sprite.LayerSetOffset(layer, proto.Offset); - args.Sprite.LayerSetVisible(layer, isTyping); + // args.Sprite.LayerSetVisible(layer, isTyping); // Corvax-TypingIndicator + // Corvax-TypingIndicator-Start + AppearanceSystem.TryGetData(uid, TypingIndicatorVisuals.State, out var state); + args.Sprite.LayerSetVisible(layer, state != TypingIndicatorState.None); + switch (state) + { + case TypingIndicatorState.Idle: + args.Sprite.LayerSetState(layer, proto.IdleState); + break; + case TypingIndicatorState.Typing: + args.Sprite.LayerSetState(layer, proto.TypingState); + break; + } + // Corvax-TypingIndicator-End } } diff --git a/Content.Client/Content.Client.csproj b/Content.Client/Content.Client.csproj index 33ee0e0a34d..2e390efd75e 100644 --- a/Content.Client/Content.Client.csproj +++ b/Content.Client/Content.Client.csproj @@ -22,6 +22,8 @@ + + diff --git a/Content.Client/Corvax/TTS/HumanoidProfileEditor.TTS.cs b/Content.Client/Corvax/TTS/HumanoidProfileEditor.TTS.cs new file mode 100644 index 00000000000..908860156c3 --- /dev/null +++ b/Content.Client/Corvax/TTS/HumanoidProfileEditor.TTS.cs @@ -0,0 +1,89 @@ +using System.Linq; +using Content.Client.Corvax.TTS; +using Content.Shared.Corvax.TTS; +using Content.Shared.Preferences; +using Robust.Shared.Random; +using Content.Corvax.Interfaces.Client; + +namespace Content.Client.Preferences.UI; + +public sealed partial class HumanoidProfileEditor +{ + private IRobustRandom _random = default!; + private TTSSystem _ttsSys = default!; + private IClientSponsorsManager? _sponsorsMgr; + private List _voiceList = default!; + private readonly List _sampleText = new() + { + "Съешь же ещё этих мягких французских булок, да выпей чаю.", + "Клоун, прекрати разбрасывать банановые кожурки офицерам под ноги!", + "Капитан, вы уверены что хотите назначить клоуна на должность главы персонала?", + "Эс Бэ! Тут человек в сером костюме, с тулбоксом и в маске! Помогите!!" + }; + + private void InitializeVoice() + { + if (!IoCManager.Instance!.TryResolveType(out _sponsorsMgr)) + return; + + _random = IoCManager.Resolve(); + _ttsSys = _entMan.System(); + _voiceList = _prototypeManager + .EnumeratePrototypes() + .Where(o => o.RoundStart) + .OrderBy(o => Loc.GetString(o.Name)) + .ToList(); + + _voiceButton.OnItemSelected += args => + { + _voiceButton.SelectId(args.Id); + SetVoice(_voiceList[args.Id].ID); + }; + + _voicePlayButton.OnPressed += _ => { PlayTTS(); }; + } + + private void UpdateTTSVoicesControls() + { + if (Profile is null || + _sponsorsMgr is null) + return; + + _voiceButton.Clear(); + + var firstVoiceChoiceId = 1; + for (var i = 0; i < _voiceList.Count; i++) + { + var voice = _voiceList[i]; + if (!HumanoidCharacterProfile.CanHaveVoice(voice, Profile.Sex)) + continue; + + var name = Loc.GetString(voice.Name); + _voiceButton.AddItem(name, i); + + if (firstVoiceChoiceId == 1) + firstVoiceChoiceId = i; + + if (voice.SponsorOnly && _sponsorsMgr != null && + !_sponsorsMgr.Prototypes.Contains(voice.ID)) + { + _voiceButton.SetItemDisabled(_voiceButton.GetIdx(i), true); + } + } + + var voiceChoiceId = _voiceList.FindIndex(x => x.ID == Profile.Voice); + if (!_voiceButton.TrySelectId(voiceChoiceId) && + _voiceButton.TrySelectId(firstVoiceChoiceId)) + { + SetVoice(_voiceList[firstVoiceChoiceId].ID); + } + } + + private void PlayTTS() + { + if (_previewDummy is null || Profile is null) + return; + + _ttsSys.RequestGlobalTTS(_random.Pick(_sampleText), Profile.Voice); + } +} diff --git a/Content.Client/Corvax/TTS/TTSSystem.cs b/Content.Client/Corvax/TTS/TTSSystem.cs new file mode 100644 index 00000000000..dc5bce8524c --- /dev/null +++ b/Content.Client/Corvax/TTS/TTSSystem.cs @@ -0,0 +1,88 @@ +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Linq; +using Content.Shared.Corvax.CCCVars; +using Content.Shared.Corvax.TTS; +using Content.Shared.Physics; +using Robust.Client.GameObjects; +using Robust.Client.Graphics; +using Robust.Client.ResourceManagement; +using Robust.Shared.Audio; +using Robust.Shared.Configuration; +using Robust.Shared.ContentPack; +using Robust.Shared.Map; +using Robust.Shared.Physics; +using Robust.Shared.Physics.Systems; +using Robust.Shared.Player; +using Robust.Shared.Utility; + +namespace Content.Client.Corvax.TTS; + +/// +/// Plays TTS audio in world +/// +// ReSharper disable once InconsistentNaming +public sealed class TTSSystem : EntitySystem +{ + [Dependency] private readonly IConfigurationManager _cfg = default!; + [Dependency] private readonly IResourceCache _resourceCache = default!; + [Dependency] private readonly SharedAudioSystem _audio = default!; + + private ISawmill _sawmill = default!; + private readonly MemoryContentRoot _contentRoot = new(); + private static readonly ResPath Prefix = ResPath.Root / "TTS"; + + private float _volume = 0.0f; + private int _fileIdx = 0; + + public override void Initialize() + { + _sawmill = Logger.GetSawmill("tts"); + _resourceCache.AddRoot(Prefix, _contentRoot); + _cfg.OnValueChanged(CCCVars.TTSVolume, OnTtsVolumeChanged, true); + SubscribeNetworkEvent(OnPlayTTS); + } + + public override void Shutdown() + { + base.Shutdown(); + _cfg.UnsubValueChanged(CCCVars.TTSVolume, OnTtsVolumeChanged); + _contentRoot.Dispose(); + } + + public void RequestGlobalTTS(string text, string voiceId) + { + RaiseNetworkEvent(new RequestGlobalTTSEvent(text, voiceId)); + } + + private void OnTtsVolumeChanged(float volume) + { + _volume = volume; + } + + private void OnPlayTTS(PlayTTSEvent ev) + { + _sawmill.Debug($"Play TTS audio {ev.Data.Length} bytes from {ev.SourceUid} entity"); + + var volume = _volume; + if (ev.IsWhisper) + volume -= 4; + + var filePath = new ResPath($"{_fileIdx++}.ogg"); + _contentRoot.AddOrUpdateFile(filePath, ev.Data); + + var audioParams = AudioParams.Default.WithVolume(volume); + var soundPath = new SoundPathSpecifier(Prefix / filePath, audioParams); + if (ev.SourceUid != null) + { + var sourceUid = GetEntity(ev.SourceUid.Value); + _audio.PlayEntity(soundPath, new EntityUid(), sourceUid); // recipient arg ignored on client + } + else + { + _audio.PlayGlobal(soundPath, Filter.Local(), false); + } + + _contentRoot.RemoveFile(filePath); + } +} diff --git a/Content.Client/Credits/CreditsWindow.xaml.cs b/Content.Client/Credits/CreditsWindow.xaml.cs index 60ac5798454..1cdc1ee4c9b 100644 --- a/Content.Client/Credits/CreditsWindow.xaml.cs +++ b/Content.Client/Credits/CreditsWindow.xaml.cs @@ -157,6 +157,7 @@ void AddSection(string title, string path, bool markup = false) AddSection(Loc.GetString("credits-window-contributors-section-title"), "GitHub.txt"); AddSection(Loc.GetString("credits-window-codebases-section-title"), "SpaceStation13.txt"); + AddSection(Loc.GetString("credits-window-tts-title"), "TTS.txt"); // Corvax-TTS AddSection(Loc.GetString("credits-window-original-remake-team-section-title"), "OriginalRemake.txt"); AddSection(Loc.GetString("credits-window-special-thanks-section-title"), "SpecialThanks.txt", true); diff --git a/Content.Client/CrewManifest/CrewManifestUi.xaml b/Content.Client/CrewManifest/CrewManifestUi.xaml index db3a7ac390d..4dbe2ed99d2 100644 --- a/Content.Client/CrewManifest/CrewManifestUi.xaml +++ b/Content.Client/CrewManifest/CrewManifestUi.xaml @@ -2,7 +2,7 @@ xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls" xmlns:ui="clr-namespace:Content.Client.CrewManifest.UI" Title="{Loc 'crew-manifest-window-title'}" - SetSize="450 750"> + SetSize="500 800"> diff --git a/Content.Client/Entry/EntryPoint.cs b/Content.Client/Entry/EntryPoint.cs index 04f0acac971..b67d624dc7b 100644 --- a/Content.Client/Entry/EntryPoint.cs +++ b/Content.Client/Entry/EntryPoint.cs @@ -1,6 +1,8 @@ using Content.Client.Administration.Managers; using Content.Client.Changelog; using Content.Client.Chat.Managers; +using Content.Client.Corvax.TTS; +using Content.Client.Options; using Content.Client.Eui; using Content.Client.Flash; using Content.Client.Fullscreen; @@ -121,6 +123,8 @@ public override void Init() _prototypeManager.RegisterIgnore("wireLayout"); _prototypeManager.RegisterIgnore("alertLevels"); _prototypeManager.RegisterIgnore("nukeopsRole"); + _prototypeManager.RegisterIgnore("stationGoal"); // Corvax-StationGoal + _prototypeManager.RegisterIgnore("loadout"); // Corvax-Loadout _componentFactory.GenerateNetIds(); _adminManager.Initialize(); diff --git a/Content.Client/Humanoid/MarkingPicker.xaml.cs b/Content.Client/Humanoid/MarkingPicker.xaml.cs index 43333439f08..64fcde98657 100644 --- a/Content.Client/Humanoid/MarkingPicker.xaml.cs +++ b/Content.Client/Humanoid/MarkingPicker.xaml.cs @@ -1,4 +1,5 @@ using System.Linq; +using Content.Corvax.Interfaces.Client; using Content.Shared.Humanoid; using Content.Shared.Humanoid.Markings; using Content.Shared.Humanoid.Prototypes; @@ -18,6 +19,7 @@ public sealed partial class MarkingPicker : Control { [Dependency] private readonly MarkingManager _markingManager = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + private IClientSponsorsManager? _sponsorsManager; // Corvax-Sponsors public Action? OnMarkingAdded; public Action? OnMarkingRemoved; @@ -123,6 +125,7 @@ public MarkingPicker() { RobustXamlLoader.Load(this); IoCManager.InjectDependencies(this); + IoCManager.Instance!.TryResolveType(out _sponsorsManager); // Corvax-Sponsors SetupCategoryButtons(); CMarkingCategoryButton.OnItemSelected += OnCategoryChange; @@ -202,6 +205,10 @@ public void Populate(string filter) var item = CMarkingsUnused.AddItem($"{GetMarkingName(marking)}", marking.Sprites[0].Frame0()); item.Metadata = marking; + // Corvax-Sponsors-Start + if (marking.SponsorOnly && _sponsorsManager != null) + item.Disabled = !_sponsorsManager.Prototypes.Contains(marking.ID); + // Corvax-Sponsors-End } CMarkingPoints.Visible = _currentMarkings.PointsLeft(_selectedMarkingCategory) != -1; diff --git a/Content.Client/Humanoid/SingleMarkingPicker.xaml.cs b/Content.Client/Humanoid/SingleMarkingPicker.xaml.cs index be3130a58bd..9e072ea4e02 100644 --- a/Content.Client/Humanoid/SingleMarkingPicker.xaml.cs +++ b/Content.Client/Humanoid/SingleMarkingPicker.xaml.cs @@ -1,4 +1,5 @@ using System.Linq; +using Content.Corvax.Interfaces.Client; using Content.Shared.Humanoid.Markings; using Robust.Client.AutoGenerated; using Robust.Client.UserInterface.Controls; @@ -11,6 +12,7 @@ namespace Content.Client.Humanoid; public sealed partial class SingleMarkingPicker : BoxContainer { [Dependency] private readonly MarkingManager _markingManager = default!; + private IClientSponsorsManager? _sponsorsManager; // Corvax-Sponsors /// /// What happens if a marking is selected. @@ -122,6 +124,7 @@ public SingleMarkingPicker() { RobustXamlLoader.Load(this); IoCManager.InjectDependencies(this); + IoCManager.Instance!.TryResolveType(out _sponsorsManager); // Corvax-Sponsors MarkingList.OnItemSelected += SelectMarking; AddButton.OnPressed += _ => @@ -190,6 +193,10 @@ public void PopulateList(string filter) { var item = MarkingList.AddItem(Loc.GetString($"marking-{id}"), marking.Sprites[0].Frame0()); item.Metadata = marking.ID; + // Corvax-Sponsors-Start + if (marking.SponsorOnly && _sponsorsManager != null) + item.Disabled = !_sponsorsManager.Prototypes.Contains(marking.ID); + // Corvax-Sponsors-End if (_markings[Slot].MarkingId == id) { diff --git a/Content.Client/IoC/ClientContentIoC.cs b/Content.Client/IoC/ClientContentIoC.cs index 70fe1916584..18b9852eee3 100644 --- a/Content.Client/IoC/ClientContentIoC.cs +++ b/Content.Client/IoC/ClientContentIoC.cs @@ -1,7 +1,8 @@ -using Content.Client.Administration.Managers; +using Content.Client.Administration.Managers; using Content.Client.Changelog; using Content.Client.Chat.Managers; using Content.Client.Clickable; +using Content.Client.Corvax.TTS; using Content.Client.Options; using Content.Client.Eui; using Content.Client.GhostKick; diff --git a/Content.Client/LateJoin/LateJoinGui.cs b/Content.Client/LateJoin/LateJoinGui.cs index 9acfb031261..3b5d0e8ef50 100644 --- a/Content.Client/LateJoin/LateJoinGui.cs +++ b/Content.Client/LateJoin/LateJoinGui.cs @@ -41,7 +41,7 @@ public sealed class LateJoinGui : DefaultWindow public LateJoinGui() { - MinSize = SetSize = new Vector2(360, 560); + MinSize = SetSize = new Vector2(450, 560); IoCManager.InjectDependencies(this); _sprites = _entitySystem.GetEntitySystem(); _crewManifest = _entitySystem.GetEntitySystem(); diff --git a/Content.Client/MassMedia/Ui/NewsWriteBoundUserInterface.cs b/Content.Client/MassMedia/Ui/NewsWriteBoundUserInterface.cs index 975dfa3f818..a3e2d210b72 100644 --- a/Content.Client/MassMedia/Ui/NewsWriteBoundUserInterface.cs +++ b/Content.Client/MassMedia/Ui/NewsWriteBoundUserInterface.cs @@ -4,6 +4,8 @@ using Content.Shared.MassMedia.Systems; using Content.Shared.MassMedia.Components; using Content.Client.GameTicking.Managers; +using Content.Shared.CCVar; +using Robust.Shared.Configuration; using Robust.Shared.Utility; namespace Content.Client.MassMedia.Ui @@ -15,7 +17,7 @@ public sealed class NewsWriteBoundUserInterface : BoundUserInterface private NewsWriteMenu? _menu; [Dependency] private readonly IEntitySystemManager _entitySystem = default!; - [Dependency] private readonly IGameTiming _gameTiming = default!; + [Dependency] private readonly IConfigurationManager _cfg = default!; private ClientGameTicker? _gameTicker; [ViewVariables] @@ -71,10 +73,16 @@ private void OnShareButtonPressed() return; var stringName = _menu.NameInput.Text; - var name = (stringName.Length <= 25 ? stringName.Trim() : $"{stringName.Trim().Substring(0, 25)}..."); + + var maxNameLength = _cfg.GetCVar(CCVars.NewsNameLimit); + var maxContentLength = _cfg.GetCVar(CCVars.NewsContentLimit); + + var name = (stringName.Length <= maxNameLength ? stringName.Trim() : $"{stringName.Trim().Substring(0, maxNameLength)}..."); + var content = (stringContent.Length <= maxContentLength ? stringContent.Trim() : $"{stringContent.Trim().Substring(0, maxContentLength)}..."); + _menu.ContentInput.TextRope = new Rope.Leaf(string.Empty); _menu.NameInput.Text = string.Empty; - SendMessage(new NewsWriteShareMessage(name, stringContent)); + SendMessage(new NewsWriteShareMessage(name, content)); } private void OnDeleteButtonPressed(int articleNum) diff --git a/Content.Client/Nuke/NukeMenu.xaml b/Content.Client/Nuke/NukeMenu.xaml index 227465341d3..bb7067565fe 100644 --- a/Content.Client/Nuke/NukeMenu.xaml +++ b/Content.Client/Nuke/NukeMenu.xaml @@ -1,8 +1,8 @@ + MinSize="280 256" + SetSize="280 256"> diff --git a/Content.Client/Options/UI/Tabs/AudioTab.xaml b/Content.Client/Options/UI/Tabs/AudioTab.xaml index 528b0ac136c..7d271d02aa4 100644 --- a/Content.Client/Options/UI/Tabs/AudioTab.xaml +++ b/Content.Client/Options/UI/Tabs/AudioTab.xaml @@ -74,6 +74,19 @@ + +