From 37292a808248408399cc5789367ef5973f55db28 Mon Sep 17 00:00:00 2001
From: Gados <42233446+OCOtheOmega@users.noreply.github.com>
Date: Mon, 31 Jul 2023 19:20:38 +0300
Subject: [PATCH 1/3] Better discord notifications
---
.../GameTicking/GameTicker.RoundFlow.cs | 2 +
.../GameTicking/RoundEndedEvent.cs | 13 ++
.../RoundNotificationsSystem.cs | 179 ++++++++++++++++++
.../_NF/GameRule/NfAdventureRuleSystem.cs | 71 ++++++-
Content.Shared/CCVar/CCVars.cs | 30 ++-
.../GameTicking/RoundRestartedEvent.cs | 15 ++
.../round-notifications/notifications.ftl | 4 +
7 files changed, 300 insertions(+), 14 deletions(-)
create mode 100644 Content.Server/Nyanotrasen/GameTicking/RoundEndedEvent.cs
create mode 100644 Content.Server/Nyanotrasen/RoundNotifications/RoundNotificationsSystem.cs
create mode 100644 Content.Shared/GameTicking/RoundRestartedEvent.cs
create mode 100644 Resources/Locale/en-US/round-notifications/notifications.ftl
diff --git a/Content.Server/GameTicking/GameTicker.RoundFlow.cs b/Content.Server/GameTicking/GameTicker.RoundFlow.cs
index fff054bcd73..8485116e3db 100644
--- a/Content.Server/GameTicking/GameTicker.RoundFlow.cs
+++ b/Content.Server/GameTicking/GameTicker.RoundFlow.cs
@@ -237,6 +237,7 @@ public void StartRound(bool force = false)
UpdateLateJoinStatus();
AnnounceRound();
UpdateInfoText();
+ RaiseLocalEvent(new RoundStartedEvent(RoundId));
#if EXCEPTION_TOLERANCE
}
@@ -359,6 +360,7 @@ public void ShowRoundEndScoreboard(string text = "")
RaiseNetworkEvent(new RoundEndMessageEvent(gamemodeTitle, roundEndText, roundDuration, RoundId,
listOfPlayerInfoFinal.Length, listOfPlayerInfoFinal, LobbySong,
new SoundCollectionSpecifier("RoundEnd").GetSound()));
+ RaiseLocalEvent(new RoundEndedEvent(RoundId, roundDuration));
}
public void RestartRound()
diff --git a/Content.Server/Nyanotrasen/GameTicking/RoundEndedEvent.cs b/Content.Server/Nyanotrasen/GameTicking/RoundEndedEvent.cs
new file mode 100644
index 00000000000..360d4dd22c9
--- /dev/null
+++ b/Content.Server/Nyanotrasen/GameTicking/RoundEndedEvent.cs
@@ -0,0 +1,13 @@
+namespace Content.Shared.GameTicking;
+
+public sealed class RoundEndedEvent : EntityEventArgs
+{
+ public int RoundId { get; }
+ public TimeSpan RoundDuration { get; }
+
+ public RoundEndedEvent(int roundId, TimeSpan roundDuration)
+ {
+ RoundId = roundId;
+ RoundDuration = roundDuration;
+ }
+}
diff --git a/Content.Server/Nyanotrasen/RoundNotifications/RoundNotificationsSystem.cs b/Content.Server/Nyanotrasen/RoundNotifications/RoundNotificationsSystem.cs
new file mode 100644
index 00000000000..daaf75a4372
--- /dev/null
+++ b/Content.Server/Nyanotrasen/RoundNotifications/RoundNotificationsSystem.cs
@@ -0,0 +1,179 @@
+using System.Net.Http;
+using System.Text;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+using Content.Shared.CCVar;
+using Content.Server.Maps;
+using Content.Shared.GameTicking;
+using Robust.Shared;
+using Robust.Shared.Configuration;
+
+namespace Content.Server.Nyanotrasen.RoundNotifications;
+
+///
+/// Listen game events and send notifications to Discord
+///
+public sealed class RoundNotificationsSystem : EntitySystem
+{
+ [Dependency] private readonly IConfigurationManager _config = default!;
+ [Dependency] private readonly IGameMapManager _gameMapManager = default!;
+
+ private ISawmill _sawmill = default!;
+ private readonly HttpClient _httpClient = new();
+
+ private string _webhookUrl = String.Empty;
+ private string _roleId = String.Empty;
+ private bool _roundStartOnly;
+ private string _serverName = string.Empty;
+
+ ///
+ public override void Initialize()
+ {
+ SubscribeLocalEvent(OnRoundRestart);
+ SubscribeLocalEvent(OnRoundStarted);
+ SubscribeLocalEvent(OnRoundEnded);
+
+ _config.OnValueChanged(CCVars.DiscordRoundWebhook, value => _webhookUrl = value, true);
+ _config.OnValueChanged(CCVars.DiscordRoundRoleId, value => _roleId = value, true);
+ _config.OnValueChanged(CCVars.DiscordRoundStartOnly, value => _roundStartOnly = value, true);
+ _config.OnValueChanged(CVars.GameHostName, OnServerNameChanged, true);
+
+ _sawmill = IoCManager.Resolve().GetSawmill("notifications");
+ }
+
+ private void OnServerNameChanged(string obj)
+ {
+ _serverName = obj;
+ }
+
+ private void OnRoundRestart(RoundRestartCleanupEvent e)
+ {
+ if (String.IsNullOrEmpty(_webhookUrl))
+ return;
+
+ var text = Loc.GetString("discord-round-new");
+
+ SendDiscordMessage(text, true, 0x91B2C7);
+ }
+
+ private void OnRoundStarted(RoundStartedEvent e)
+ {
+ if (String.IsNullOrEmpty(_webhookUrl))
+ return;
+
+ var map = _gameMapManager.GetSelectedMap();
+ var mapName = map?.MapName ?? Loc.GetString("discord-round-unknown-map");
+ var text = Loc.GetString("discord-round-start",
+ ("id", e.RoundId),
+ ("map", mapName));
+
+ SendDiscordMessage(text, false);
+ }
+
+ private void OnRoundEnded(RoundEndedEvent e)
+ {
+ if (String.IsNullOrEmpty(_webhookUrl) || _roundStartOnly)
+ return;
+
+ var text = Loc.GetString("discord-round-end",
+ ("id", e.RoundId),
+ ("hours", Math.Truncate(e.RoundDuration.TotalHours)),
+ ("minutes", e.RoundDuration.Minutes),
+ ("seconds", e.RoundDuration.Seconds));
+
+ SendDiscordMessage(text, false, 0xB22B27);
+ }
+
+ private async void SendDiscordMessage(string text, bool ping = false, int color = 0x41F097)
+ {
+
+ // Limit server name to 1500 characters, in case someone tries to be a little funny
+ var serverName = _serverName[..Math.Min(_serverName.Length, 1500)];
+ var message = "";
+ if (!String.IsNullOrEmpty(_roleId) && ping)
+ message = $"<@&{_roleId}>";
+
+ // Build the embed
+ var payload = new WebhookPayload
+ {
+ Message = message,
+ Embeds = new List