diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml deleted file mode 100644 index 7ff9017cb0..0000000000 --- a/.github/ISSUE_TEMPLATE/config.yml +++ /dev/null @@ -1,4 +0,0 @@ -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 to the Space Wizards privately so they can fix them before they are publicly disclosed. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index aba549332f..51f9de8baf 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -1,8 +1,8 @@ --- -name: Request a Feature -about: "Template for noting future planned features. Please ask for approval in the Discord if you aren't an organization Member before posting a feature request" +name: Request a feature +about: "Please outline your request in Discord first if you aren't a maintainer." title: '' -labels: '' +labels: ["Type: Feature"] assignees: '' --- diff --git a/.github/ISSUE_TEMPLATE/issue_report.md b/.github/ISSUE_TEMPLATE/issue_report.md index ab82181197..c74f24554a 100644 --- a/.github/ISSUE_TEMPLATE/issue_report.md +++ b/.github/ISSUE_TEMPLATE/issue_report.md @@ -1,8 +1,8 @@ --- -name: Report an Issue -about: "Any general issues you have during play or with the codebase" +name: Report an issue +about: "Any issues found in gameplay or the codebase" title: '' -labels: '' +labels: 'Type: Bug' assignees: '' --- diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml index 877273d764..79cfdd83cd 100644 --- a/.github/workflows/changelog.yml +++ b/.github/workflows/changelog.yml @@ -16,41 +16,40 @@ jobs: permissions: contents: write steps: - - name: Checkout Master - uses: actions/checkout@v3 - with: - token: ${{ secrets.BOT_TOKEN }} - ref: "${{ vars.CHANGELOG_BRANCH }}" + - name: Checkout Master + uses: actions/checkout@v3 + with: + token: ${{ secrets.BOT_TOKEN }} + ref: ${{ vars.CHANGELOG_BRANCH }} - - name: Setup Git - run: | - git config --global user.name "${{ vars.CHANGELOG_USER }}" - git config --global user.email "${{ vars.CHANGELOG_EMAIL }}" - shell: bash + - name: Setup Git + run: | + git config --global user.name "${{ vars.CHANGELOG_USER }}" + git config --global user.email "${{ vars.CHANGELOG_EMAIL }}" + shell: bash - - name: Setup Node - uses: actions/setup-node@v3 - with: - node-version: 18.x + - name: Setup Node + uses: actions/setup-node@v3 + with: + node-version: 18.x - - name: Install Dependencies - run: | - cd "Tools/changelogs" - npm install - shell: bash - continue-on-error: true + - name: Install Dependencies + run: | + cd "Tools/changelogs" + npm install + shell: bash - - name: Generate Changelog - run: | - cd "Tools/changelogs" - node changelog.js - shell: bash - continue-on-error: true + - name: Generate Changelog + run: | + cd "Tools/changelogs" + node changelog.js + shell: bash - - name: Commit Changelog - run: | - git add *.yml - git commit -m "${{ vars.CHANGELOG_MESSAGE }} (#${{ env.PR_NUMBER }})" - git push - shell: bash - continue-on-error: true + - name: Commit Changelog + run: | + git pull origin master + git add *.yml + git commit -m "${{ vars.CHANGELOG_MESSAGE }} (#${{ env.PR_NUMBER }})" + git push + shell: bash + continue-on-error: true diff --git a/.github/workflows/discord-changelog.yml b/.github/workflows/discord-changelog.yml new file mode 100644 index 0000000000..74be415432 --- /dev/null +++ b/.github/workflows/discord-changelog.yml @@ -0,0 +1,24 @@ +name: Discord Changelog + +on: + workflow_dispatch: + schedule: + - cron: '0 6 * * *' + +jobs: + publish_changelog: + runs-on: ubuntu-latest + steps: + + - name: checkout + uses: actions/checkout@v3 + with: + ref: master + + - name: Publish changelog + run: Tools/actions_changelogs_since_last_run.py + env: + CHANGELOG_DIR: ${{ vars.CHANGELOG_DIR }} + CHANGELOG_WEBHOOK: ${{ secrets.CHANGELOG_WEBHOOK }} + GITHUB_TOKEN: ${{ secrets.BOT_TOKEN }} + continue-on-error: true diff --git a/Content.Client/Actions/ActionsSystem.cs b/Content.Client/Actions/ActionsSystem.cs index b992e77256..90158ba81e 100644 --- a/Content.Client/Actions/ActionsSystem.cs +++ b/Content.Client/Actions/ActionsSystem.cs @@ -65,6 +65,7 @@ private void OnEntityTargetHandleState(EntityUid uid, EntityTargetActionComponen return; component.Whitelist = state.Whitelist; + component.Blacklist = state.Blacklist; component.CanTargetSelf = state.CanTargetSelf; BaseHandleState(uid, component, state); } diff --git a/Content.Client/Administration/Systems/BwoinkSystem.cs b/Content.Client/Administration/Systems/BwoinkSystem.cs index a3b295d6b6..8316204771 100644 --- a/Content.Client/Administration/Systems/BwoinkSystem.cs +++ b/Content.Client/Administration/Systems/BwoinkSystem.cs @@ -1,10 +1,6 @@ -#nullable enable -using Content.Client.UserInterface.Systems.Bwoink; -using Content.Shared.Administration; +using Content.Shared.Administration; using JetBrains.Annotations; -using Robust.Client.Audio; using Robust.Shared.Network; -using Robust.Shared.Player; using Robust.Shared.Timing; namespace Content.Client.Administration.Systems @@ -13,8 +9,6 @@ namespace Content.Client.Administration.Systems public sealed class BwoinkSystem : SharedBwoinkSystem { [Dependency] private readonly IGameTiming _timing = default!; - [Dependency] private readonly AudioSystem _audio = default!; - [Dependency] private readonly AdminSystem _adminSystem = default!; public event EventHandler? OnBwoinkTextMessageRecieved; private (TimeSpan Timestamp, bool Typing) _lastTypingUpdateSent; @@ -26,10 +20,6 @@ protected override void OnBwoinkTextMessage(BwoinkTextMessage message, EntitySes public void Send(NetUserId channelId, string text, bool playSound) { - var info = _adminSystem.PlayerInfos.GetValueOrDefault(channelId)?.Connected ?? true; - _audio.PlayGlobal(info ? AHelpUIController.AHelpSendSound : AHelpUIController.AHelpErrorSound, - Filter.Local(), false); - // 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)); diff --git a/Content.Client/Administration/UI/AdminUIHelpers.cs b/Content.Client/Administration/UI/AdminUIHelpers.cs index 89ab33e931..7fa8172891 100644 --- a/Content.Client/Administration/UI/AdminUIHelpers.cs +++ b/Content.Client/Administration/UI/AdminUIHelpers.cs @@ -50,7 +50,7 @@ public static bool TryConfirm(Button button, Dictionary AnnouncerSources { get; } = new(); + public float AnnouncerVolume { get; private set; } public override void Initialize() @@ -28,8 +29,10 @@ public override void Initialize() AnnouncerVolume = _config.GetCVar(CCVars.AnnouncerVolume) * 100f / ContentAudioSystem.AnnouncerMultiplier; - SubscribeNetworkEvent(OnAnnouncementReceived); _config.OnValueChanged(CCVars.AnnouncerVolume, OnAnnouncerVolumeChanged); + _config.OnValueChanged(CCVars.AnnouncerDisableMultipleSounds, OnAnnouncerDisableMultipleSounds); + + SubscribeNetworkEvent(OnAnnouncementReceived); } public override void Shutdown() @@ -37,6 +40,7 @@ public override void Shutdown() base.Shutdown(); _config.UnsubValueChanged(CCVars.AnnouncerVolume, OnAnnouncerVolumeChanged); + _config.UnsubValueChanged(CCVars.AnnouncerDisableMultipleSounds, OnAnnouncerDisableMultipleSounds); } @@ -44,10 +48,23 @@ private void OnAnnouncerVolumeChanged(float value) { AnnouncerVolume = value; - if (AnnouncerSource != null) - AnnouncerSource.Gain = AnnouncerVolume; + foreach (var source in AnnouncerSources) + source.Gain = AnnouncerVolume; } + private void OnAnnouncerDisableMultipleSounds(bool value) + { + if (!value) + return; + + foreach (var audioSource in AnnouncerSources.ToList()) + { + audioSource.Dispose(); + AnnouncerSources.Remove(audioSource); + } + } + + private void OnAnnouncementReceived(AnnouncementSendEvent ev) { if (!ev.Recipients.Contains(_player.LocalSession!.UserId) @@ -56,14 +73,28 @@ private void OnAnnouncementReceived(AnnouncementSendEvent ev) return; var source = _audioManager.CreateAudioSource(resource); - if (source != null) + if (source == null) + return; + + source.Gain = AnnouncerVolume * SharedAudioSystem.VolumeToGain(ev.AudioParams.Volume); + source.Global = true; + + if (_config.GetCVar(CCVars.AnnouncerDisableMultipleSounds)) + { + foreach (var audioSource in AnnouncerSources.ToList()) + { + audioSource.Dispose(); + AnnouncerSources.Remove(audioSource); + } + } + + foreach (var audioSource in AnnouncerSources.ToList().Where(audioSource => !audioSource.Playing)) { - source.Gain = AnnouncerVolume * SharedAudioSystem.VolumeToGain(ev.AudioParams.Volume); - source.Global = true; + audioSource.Dispose(); + AnnouncerSources.Remove(audioSource); } - AnnouncerSource?.Dispose(); - AnnouncerSource = source; - AnnouncerSource?.StartPlaying(); + AnnouncerSources.Add(source); + source.StartPlaying(); } } diff --git a/Content.Client/Audio/Jukebox/JukeboxBoundUserInterface.cs b/Content.Client/Audio/Jukebox/JukeboxBoundUserInterface.cs new file mode 100644 index 0000000000..072730d65d --- /dev/null +++ b/Content.Client/Audio/Jukebox/JukeboxBoundUserInterface.cs @@ -0,0 +1,119 @@ +using Content.Shared.Audio.Jukebox; +using Robust.Client.Audio; +using Robust.Client.Player; +using Robust.Shared.Audio.Components; +using Robust.Shared.Player; +using Robust.Shared.Prototypes; + +namespace Content.Client.Audio.Jukebox; + +public sealed class JukeboxBoundUserInterface : BoundUserInterface +{ + [Dependency] private readonly IPlayerManager _player = default!; + [Dependency] private readonly IPrototypeManager _protoManager = default!; + + [ViewVariables] + private JukeboxMenu? _menu; + + public JukeboxBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey) + { + IoCManager.InjectDependencies(this); + } + + protected override void Open() + { + base.Open(); + + _menu = new JukeboxMenu(); + _menu.OnClose += Close; + _menu.OpenCentered(); + + _menu.OnPlayPressed += args => + { + if (args) + { + SendMessage(new JukeboxPlayingMessage()); + } + else + { + SendMessage(new JukeboxPauseMessage()); + } + }; + + _menu.OnStopPressed += () => + { + SendMessage(new JukeboxStopMessage()); + }; + + _menu.OnSongSelected += SelectSong; + + _menu.SetTime += SetTime; + PopulateMusic(); + Reload(); + } + + /// + /// Reloads the attached menu if it exists. + /// + public void Reload() + { + if (_menu == null || !EntMan.TryGetComponent(Owner, out JukeboxComponent? jukebox)) + return; + + _menu.SetAudioStream(jukebox.AudioStream); + + if (_protoManager.TryIndex(jukebox.SelectedSongId, out var songProto)) + { + var length = EntMan.System().GetAudioLength(songProto.Path.Path.ToString()); + _menu.SetSelectedSong(songProto.Name, (float) length.TotalSeconds); + } + else + { + _menu.SetSelectedSong(string.Empty, 0f); + } + } + + public void PopulateMusic() + { + _menu?.Populate(_protoManager.EnumeratePrototypes()); + } + + public void SelectSong(ProtoId songid) + { + SendMessage(new JukeboxSelectedMessage(songid)); + } + + public void SetTime(float time) + { + var sentTime = time; + + // You may be wondering, what the fuck is this + // Well we want to be able to predict the playback slider change, of which there are many ways to do it + // We can't just use SendPredictedMessage because it will reset every tick and audio updates every frame + // so it will go BRRRRT + // Using ping gets us close enough that it SHOULD, MOST OF THE TIME, fall within the 0.1 second tolerance + // that's still on engine so our playback position never gets corrected. + if (EntMan.TryGetComponent(Owner, out JukeboxComponent? jukebox) && + EntMan.TryGetComponent(jukebox.AudioStream, out AudioComponent? audioComp)) + { + audioComp.PlaybackPosition = time; + } + + SendMessage(new JukeboxSetTimeMessage(sentTime)); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) + return; + + if (_menu == null) + return; + + _menu.OnClose -= Close; + _menu.Dispose(); + _menu = null; + } +} + diff --git a/Content.Client/Audio/Jukebox/JukeboxMenu.xaml b/Content.Client/Audio/Jukebox/JukeboxMenu.xaml new file mode 100644 index 0000000000..e8d39a9b11 --- /dev/null +++ b/Content.Client/Audio/Jukebox/JukeboxMenu.xaml @@ -0,0 +1,18 @@ + + + + + + +