[feat] Sockets, i guess mm hmm
# Conflicts: # Content.Server/Administration/Systems/BwoinkSystem.cs # Content.Server/Chat/Managers/ChatManager.cs # Content.Server/Entry/EntryPoint.cs # Content.Server/GameTicking/GameTicker.RoundFlow.cs # Content.Server/IoC/ServerContentIoC.cs # Content.Server/RoundEnd/RoundEndSystem.cs # Content.Server/Shuttles/Systems/EmergencyShuttleSystem.Console.cs # Content.Server/Shuttles/Systems/EmergencyShuttleSystem.cs # Content.Shared/CCVar/CCVars.cs
This commit is contained in:
@@ -3,10 +3,10 @@ using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.Administration.Managers;
|
||||
using Content.Server.Discord;
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.CCVar;
|
||||
@@ -346,13 +346,13 @@ namespace Content.Server.Administration.Systems
|
||||
{
|
||||
Username = username,
|
||||
AvatarUrl = string.IsNullOrWhiteSpace(_avatarUrl) ? null : _avatarUrl,
|
||||
Embeds = new List<WebhookEmbed>
|
||||
Embeds = new List<Embed>
|
||||
{
|
||||
new()
|
||||
{
|
||||
Description = messages,
|
||||
Color = color,
|
||||
Footer = new WebhookEmbedFooter
|
||||
Footer = new EmbedFooter
|
||||
{
|
||||
Text = $"{serverName} ({round})",
|
||||
IconUrl = string.IsNullOrWhiteSpace(_footerIconUrl) ? null : _footerIconUrl
|
||||
@@ -495,7 +495,7 @@ namespace Content.Server.Administration.Systems
|
||||
private static string GenerateAHelpMessage(string username, string message, bool admin, string roundTime, GameRunLevel roundState, bool noReceivers = false)
|
||||
{
|
||||
var stringbuilder = new StringBuilder();
|
||||
|
||||
|
||||
if (admin)
|
||||
stringbuilder.Append(":outbox_tray:");
|
||||
else if (noReceivers)
|
||||
@@ -509,6 +509,118 @@ namespace Content.Server.Administration.Systems
|
||||
stringbuilder.Append(message);
|
||||
return stringbuilder.ToString();
|
||||
}
|
||||
|
||||
// https://discord.com/developers/docs/resources/channel#message-object-message-structure
|
||||
private struct WebhookPayload
|
||||
{
|
||||
[JsonPropertyName("username")]
|
||||
public string Username { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("avatar_url")]
|
||||
public string? AvatarUrl { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("embeds")]
|
||||
public List<Embed>? Embeds { get; set; } = null;
|
||||
|
||||
[JsonPropertyName("allowed_mentions")]
|
||||
public Dictionary<string, string[]> AllowedMentions { get; set; } =
|
||||
new()
|
||||
{
|
||||
{ "parse", Array.Empty<string>() },
|
||||
};
|
||||
|
||||
public WebhookPayload()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
// https://discord.com/developers/docs/resources/channel#embed-object-embed-structure
|
||||
private struct Embed
|
||||
{
|
||||
[JsonPropertyName("description")]
|
||||
public string Description { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("color")]
|
||||
public int Color { get; set; } = 0;
|
||||
|
||||
[JsonPropertyName("footer")]
|
||||
public EmbedFooter? Footer { get; set; } = null;
|
||||
|
||||
public Embed()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
// https://discord.com/developers/docs/resources/channel#embed-object-embed-footer-structure
|
||||
private struct EmbedFooter
|
||||
{
|
||||
[JsonPropertyName("text")]
|
||||
public string Text { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("icon_url")]
|
||||
public string? IconUrl { get; set; }
|
||||
|
||||
public EmbedFooter()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
// https://discord.com/developers/docs/resources/webhook#webhook-object-webhook-structure
|
||||
private struct WebhookData
|
||||
{
|
||||
[JsonPropertyName("guild_id")]
|
||||
public string? GuildId { get; set; } = null;
|
||||
|
||||
[JsonPropertyName("channel_id")]
|
||||
public string? ChannelId { get; set; } = null;
|
||||
|
||||
public WebhookData()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
//WD-EDIT
|
||||
public void SendUtkaBwoinkMessage(NetUserId receiver, string sender, string text)
|
||||
{
|
||||
var bwoinkText = $"[color=red](D) {sender}[/color]: {text}";
|
||||
_playerManager.TryGetUserId(sender, out var senderId);
|
||||
var msg = new BwoinkTextMessage(receiver, senderId, bwoinkText);
|
||||
|
||||
LogBwoink(msg);
|
||||
|
||||
var admins = GetTargetAdmins();
|
||||
|
||||
// Notify all admins
|
||||
foreach (var channel in admins)
|
||||
{
|
||||
RaiseNetworkEvent(msg, channel);
|
||||
}
|
||||
|
||||
// Notify player
|
||||
if (_playerManager.TryGetSessionById(receiver, out var session))
|
||||
{
|
||||
if (!admins.Contains(session.ConnectedClient))
|
||||
RaiseNetworkEvent(msg, session.ConnectedClient);
|
||||
}
|
||||
|
||||
var sendsWebhook = _webhookUrl != string.Empty;
|
||||
if (sendsWebhook)
|
||||
{
|
||||
if (!_messageQueues.ContainsKey(msg.UserId))
|
||||
_messageQueues[msg.UserId] = new Queue<string>();
|
||||
|
||||
var str = text;
|
||||
var unameLength = sender.Length;
|
||||
|
||||
if (unameLength + str.Length + _maxAdditionalChars > DescriptionMax)
|
||||
{
|
||||
str = str[..(DescriptionMax - _maxAdditionalChars - unameLength)];
|
||||
}
|
||||
_messageQueues[msg.UserId].Enqueue(GenerateAHelpMessage(sender, str, true,
|
||||
_gameTicker.RoundDuration().ToString("hh\\:mm\\:ss"), _gameTicker.RunLevel));
|
||||
}
|
||||
}
|
||||
//WD-EDIT
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ using Content.Server.Administration.Managers;
|
||||
using Content.Server.Administration.Systems;
|
||||
using Content.Server.MoMMI;
|
||||
using Content.Server.Preferences.Managers;
|
||||
using Content.Server.UtkaIntegration;
|
||||
using Content.Server.White.Sponsors;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.CCVar;
|
||||
@@ -49,6 +50,7 @@ namespace Content.Server.Chat.Managers
|
||||
|
||||
/// WD-EDIT
|
||||
[Dependency] private readonly SponsorsManager _sponsorsManager = default!;
|
||||
[Dependency] private readonly UtkaTCPWrapper _utkaSocketWrapper = default!;
|
||||
/// WD-EDIT
|
||||
|
||||
/// <summary>
|
||||
@@ -170,7 +172,7 @@ namespace Content.Server.Chat.Managers
|
||||
|
||||
public void SendHookOOC(string sender, string message)
|
||||
{
|
||||
if (!_oocEnabled && _configurationManager.GetCVar(CCVars.DisablingOOCDisablesRelay))
|
||||
if (_configurationManager.GetCVar(CCVars.DisableHookedOOC))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -179,6 +181,28 @@ namespace Content.Server.Chat.Managers
|
||||
_adminLogger.Add(LogType.Chat, LogImpact.Low, $"Hook OOC from {sender}: {message}");
|
||||
}
|
||||
|
||||
//WD-EDIT
|
||||
public void SendHookAdminChat(string sender, string message)
|
||||
{
|
||||
var admins = _adminManager.ActiveAdmins;
|
||||
|
||||
var wrappedMessage = Loc.GetString("chat-manager-send-admin-chat-wrap-message",
|
||||
("adminChannelName", Loc.GetString("chat-manager-admin-discord-channel-name")),
|
||||
("playerName", sender), ("message", FormattedMessage.EscapeText(message)));
|
||||
|
||||
ChatMessageToMany(ChatChannel.Admin, message, wrappedMessage, EntityUid.Invalid, false, true, admins.Select(p => p.ConnectedClient));
|
||||
|
||||
var asayEventMessage = new UtkaChatEventMessage()
|
||||
{
|
||||
Command = "asay",
|
||||
Ckey = sender,
|
||||
Message = message
|
||||
};
|
||||
|
||||
_utkaSocketWrapper.SendMessageToAll(asayEventMessage);
|
||||
}
|
||||
//WD-EDIT
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public OOC Chat API
|
||||
@@ -254,6 +278,17 @@ namespace Content.Server.Chat.Managers
|
||||
ChatMessageToAll(ChatChannel.OOC, message, wrappedMessage, EntityUid.Invalid, hideChat: false, recordReplay: true, colorOverride: colorOverride, author: player.UserId);
|
||||
_mommiLink.SendOOCMessage(player.Name, message);
|
||||
_adminLogger.Add(LogType.Chat, LogImpact.Low, $"OOC from {player:Player}: {message}");
|
||||
|
||||
//WD-EDIT
|
||||
var toUtkaMessage = new UtkaChatEventMessage()
|
||||
{
|
||||
Command = "ooc",
|
||||
Ckey = player.Name,
|
||||
Message = message,
|
||||
};
|
||||
|
||||
_utkaSocketWrapper.SendMessageToAll(toUtkaMessage);
|
||||
//WD-EDIT
|
||||
}
|
||||
|
||||
private void SendAdminChat(ICommonSession player, string message)
|
||||
@@ -284,6 +319,17 @@ namespace Content.Server.Chat.Managers
|
||||
}
|
||||
|
||||
_adminLogger.Add(LogType.Chat, $"Admin chat from {player:Player}: {message}");
|
||||
|
||||
//WD-EDIT
|
||||
var asayEventMessage = new UtkaChatEventMessage()
|
||||
{
|
||||
Command = "asay",
|
||||
Ckey = player.Name,
|
||||
Message = message
|
||||
};
|
||||
|
||||
_utkaSocketWrapper.SendMessageToAll(asayEventMessage);
|
||||
//WD-EDIT
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -21,6 +21,7 @@ namespace Content.Server.Chat.Managers
|
||||
void TrySendOOCMessage(ICommonSession player, string message, OOCChatType type);
|
||||
|
||||
void SendHookOOC(string sender, string message);
|
||||
void SendHookAdminChat(string sender, string message); // WD-EDIT
|
||||
void SendAdminAnnouncement(string message);
|
||||
void SendAdminAlert(string message);
|
||||
void SendAdminAlert(EntityUid player, string message);
|
||||
|
||||
@@ -8,6 +8,7 @@ using Content.Server.Speech.Components;
|
||||
using Content.Server.Speech.EntitySystems;
|
||||
using Content.Server.Station.Components;
|
||||
using Content.Server.Station.Systems;
|
||||
using Content.Server.UtkaIntegration;
|
||||
using Content.Shared.ActionBlocker;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared.Chat;
|
||||
@@ -56,6 +57,10 @@ public sealed partial class ChatSystem : SharedChatSystem
|
||||
[Dependency] private readonly SharedInteractionSystem _interactionSystem = default!;
|
||||
[Dependency] private readonly ReplacementAccentSystem _wordreplacement = default!;
|
||||
|
||||
//WD-EDIT
|
||||
[Dependency] private readonly UtkaTCPWrapper _utkaSockets = default!;
|
||||
//WD-EDIT
|
||||
|
||||
public const int VoiceRange = 10; // how far voice goes in world units
|
||||
public const int WhisperClearRange = 2; // how far whisper goes while still being understandable, in world units
|
||||
public const int WhisperMuffledRange = 5; // how far whisper goes at all, in world units
|
||||
@@ -571,6 +576,28 @@ public sealed partial class ChatSystem : SharedChatSystem
|
||||
_adminLogger.Add(LogType.Chat, LogImpact.Low, $"Emote from {ToPrettyString(source):user} as {name}: {action}");
|
||||
else
|
||||
_adminLogger.Add(LogType.Chat, LogImpact.Low, $"Emote from {ToPrettyString(source):user}: {action}");
|
||||
|
||||
//WD-EDIT
|
||||
|
||||
string ckey = string.Empty;
|
||||
|
||||
if (TryComp<ActorComponent>(source, out var actorComponent))
|
||||
{
|
||||
ckey = actorComponent.PlayerSession.Name;
|
||||
}
|
||||
|
||||
if(string.IsNullOrEmpty(ckey)) return;
|
||||
|
||||
var utkaEmoteEvent = new UtkaChatMeEvent()
|
||||
{
|
||||
Ckey = ckey,
|
||||
Message = action,
|
||||
CharacterName = MetaData(source).EntityName
|
||||
};
|
||||
|
||||
_utkaSockets.SendMessageToAll(utkaEmoteEvent);
|
||||
|
||||
//WD-EDIT
|
||||
}
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="JetBrains.Annotations" Version="2022.1.0" PrivateAssets="All" />
|
||||
<PackageReference Include="NetCoreServer" Version="6.7.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Content.Packaging\Content.Packaging.csproj" />
|
||||
|
||||
@@ -29,6 +29,7 @@ using Robust.Shared.ContentPack;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.Utility;
|
||||
using Content.Server.UtkaIntegration;
|
||||
using Content.Server.White.JoinQueue;
|
||||
using Content.Server.White.Sponsors;
|
||||
|
||||
@@ -146,6 +147,14 @@ namespace Content.Server.Entry
|
||||
IoCManager.Resolve<IGameMapManager>().Initialize();
|
||||
IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<GameTicker>().PostInitialize();
|
||||
IoCManager.Resolve<IBanManager>().Initialize();
|
||||
IoCManager.Resolve<IBqlQueryManager>().DoAutoRegistrations();
|
||||
IoCManager.Resolve<RoleBanManager>().Initialize();
|
||||
|
||||
//WD-EDIT
|
||||
IoCManager.Resolve<UtkaTCPWrapper>().Initialize();
|
||||
UtkaTCPServer.RegisterCommands();
|
||||
//WD-EDIT
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,8 @@ using Robust.Shared.Network;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Utility;
|
||||
using Content.Server.UtkaIntegration;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Content.Server.GameTicking
|
||||
{
|
||||
@@ -28,6 +30,10 @@ namespace Content.Server.GameTicking
|
||||
[Dependency] private readonly DiscordWebhook _discord = default!;
|
||||
[Dependency] private readonly ITaskManager _taskManager = default!;
|
||||
|
||||
//WD-EDIT
|
||||
[Dependency] private readonly UtkaTCPWrapper _utkaSocketWrapper = default!;
|
||||
//WD-EDIT
|
||||
|
||||
private static readonly Counter RoundNumberMetric = Metrics.CreateCounter(
|
||||
"ss14_round_number",
|
||||
"Round number.");
|
||||
@@ -255,6 +261,7 @@ namespace Content.Server.GameTicking
|
||||
AnnounceRound();
|
||||
UpdateInfoText();
|
||||
RaiseLocalEvent(new RoundStartedEvent(RoundId)); // WD-EDIT
|
||||
SendRoundStatus("game_started"); //WD-EDIT
|
||||
|
||||
#if EXCEPTION_TOLERANCE
|
||||
}
|
||||
@@ -435,6 +442,7 @@ namespace Content.Server.GameTicking
|
||||
UpdateInfoText();
|
||||
|
||||
ReqWindowAttentionAll();
|
||||
SendRoundStatus("lobby_loaded"); //WD-EDIT
|
||||
}
|
||||
}
|
||||
|
||||
@@ -517,6 +525,22 @@ namespace Content.Server.GameTicking
|
||||
return true;
|
||||
}
|
||||
|
||||
//WD-EDIT
|
||||
private void SendRoundStatus(string status)
|
||||
{
|
||||
if (!_postInitialized)
|
||||
return;
|
||||
|
||||
var utkaRoundStatusEvent = new UtkaRoundStatusEvent()
|
||||
{
|
||||
Message = status
|
||||
};
|
||||
|
||||
_utkaSocketWrapper.SendMessageToAll(utkaRoundStatusEvent);
|
||||
|
||||
}
|
||||
//WD-EDIT
|
||||
|
||||
private void UpdateRoundFlow(float frameTime)
|
||||
{
|
||||
if (RunLevel == GameRunLevel.InRound)
|
||||
|
||||
@@ -19,6 +19,7 @@ using Content.Server.ServerInfo;
|
||||
using Content.Server.ServerUpdates;
|
||||
using Content.Server.Voting.Managers;
|
||||
using Content.Server.Worldgen.Tools;
|
||||
using Content.Server.UtkaIntegration;
|
||||
using Content.Server.White.JoinQueue;
|
||||
using Content.Server.White.Sponsors;
|
||||
using Content.Shared.Administration.Logs;
|
||||
@@ -64,6 +65,7 @@ namespace Content.Server.IoC
|
||||
// WD-EDIT
|
||||
IoCManager.Register<SponsorsManager>();
|
||||
IoCManager.Register<JoinQueueManager>();
|
||||
IoCManager.Register<UtkaTCPWrapper>();
|
||||
// WD-EDIT
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ using Content.Server.Shuttles.Components;
|
||||
using Content.Server.Shuttles.Systems;
|
||||
using Content.Server.Station.Components;
|
||||
using Content.Server.Station.Systems;
|
||||
using Content.Server.UtkaIntegration;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.GameTicking;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
@@ -45,6 +46,10 @@ namespace Content.Server.RoundEnd
|
||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||
[Dependency] private readonly StationSystem _stationSystem = default!;
|
||||
|
||||
//WD-EDIT
|
||||
[Dependency] private readonly UtkaTCPWrapper _utkaSocketWrapper = default!;
|
||||
//WD-EDIT
|
||||
|
||||
public TimeSpan DefaultCooldownDuration { get; set; } = TimeSpan.FromSeconds(30);
|
||||
|
||||
/// <summary>
|
||||
@@ -52,15 +57,19 @@ namespace Content.Server.RoundEnd
|
||||
/// </summary>
|
||||
public TimeSpan DefaultCountdownDuration { get; set; } = TimeSpan.FromMinutes(10);
|
||||
|
||||
private CancellationTokenSource? _countdownTokenSource = null;
|
||||
private CancellationTokenSource? _cooldownTokenSource = null;
|
||||
public TimeSpan? LastCountdownStart { get; set; } = null;
|
||||
public TimeSpan? ExpectedCountdownEnd { get; set; } = null;
|
||||
private CancellationTokenSource? _countdownTokenSource;
|
||||
private CancellationTokenSource? _cooldownTokenSource;
|
||||
|
||||
public TimeSpan? LastCountdownStart { get; set; }
|
||||
|
||||
public TimeSpan? ExpectedCountdownEnd { get; set; }
|
||||
|
||||
public TimeSpan? ExpectedShuttleLength => ExpectedCountdownEnd - LastCountdownStart;
|
||||
|
||||
public TimeSpan? ShuttleTimeLeft => ExpectedCountdownEnd - _gameTiming.CurTime;
|
||||
|
||||
public TimeSpan AutoCallStartTime;
|
||||
private bool _autoCalledBefore = false;
|
||||
private bool _autoCalledBefore;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -100,9 +109,12 @@ namespace Content.Server.RoundEnd
|
||||
/// </summary>
|
||||
public EntityUid? GetStation()
|
||||
{
|
||||
AllEntityQuery<StationEmergencyShuttleComponent, StationDataComponent>().MoveNext(out _, out _, out var data);
|
||||
AllEntityQuery<StationEmergencyShuttleComponent, StationDataComponent>()
|
||||
.MoveNext(out _, out _, out var data);
|
||||
|
||||
if (data == null)
|
||||
return null;
|
||||
|
||||
var targetGrid = _stationSystem.GetLargestGrid(data);
|
||||
return targetGrid == null ? null : Transform(targetGrid.Value).MapUid;
|
||||
}
|
||||
@@ -112,13 +124,9 @@ namespace Content.Server.RoundEnd
|
||||
/// </summary>
|
||||
public EntityUid? GetCentcomm()
|
||||
{
|
||||
if (AllEntityQuery<StationCentcommComponent, TransformComponent>()
|
||||
.MoveNext(out var centcomm, out var xform))
|
||||
{
|
||||
return xform.MapUid;
|
||||
}
|
||||
|
||||
return null;
|
||||
return AllEntityQuery<StationCentcommComponent, TransformComponent>().MoveNext(out _, out var xform)
|
||||
? xform.MapUid
|
||||
: null;
|
||||
}
|
||||
|
||||
public bool CanCallOrRecall()
|
||||
@@ -131,7 +139,11 @@ namespace Content.Server.RoundEnd
|
||||
return _countdownTokenSource != null;
|
||||
}
|
||||
|
||||
public void RequestRoundEnd(EntityUid? requester = null, bool checkCooldown = true, string text = "round-end-system-shuttle-called-announcement", string name = "Station")
|
||||
public void RequestRoundEnd(
|
||||
EntityUid? requester = null,
|
||||
bool checkCooldown = true,
|
||||
string text = "round-end-system-shuttle-called-announcement",
|
||||
string name = "Station")
|
||||
{
|
||||
var duration = DefaultCountdownDuration;
|
||||
|
||||
@@ -149,18 +161,28 @@ namespace Content.Server.RoundEnd
|
||||
RequestRoundEnd(duration, requester, checkCooldown, text, name);
|
||||
}
|
||||
|
||||
public void RequestRoundEnd(TimeSpan countdownTime, EntityUid? requester = null, bool checkCooldown = true, string text = "round-end-system-shuttle-called-announcement", string name = "Station")
|
||||
public void RequestRoundEnd(
|
||||
TimeSpan countdownTime,
|
||||
EntityUid? requester = null,
|
||||
bool checkCooldown = true,
|
||||
string text = "round-end-system-shuttle-called-announcement",
|
||||
string name = "Station")
|
||||
{
|
||||
if (_gameTicker.RunLevel != GameRunLevel.InRound) return;
|
||||
if (_gameTicker.RunLevel != GameRunLevel.InRound)
|
||||
return;
|
||||
|
||||
if (checkCooldown && _cooldownTokenSource != null) return;
|
||||
if (checkCooldown && _cooldownTokenSource != null)
|
||||
return;
|
||||
|
||||
if (_countdownTokenSource != null) return;
|
||||
_countdownTokenSource = new();
|
||||
if (_countdownTokenSource != null)
|
||||
return;
|
||||
|
||||
_countdownTokenSource = new CancellationTokenSource();
|
||||
|
||||
if (requester != null)
|
||||
{
|
||||
_adminLogger.Add(LogType.ShuttleCalled, LogImpact.High, $"Shuttle called by {ToPrettyString(requester.Value):user}");
|
||||
_adminLogger.Add(LogType.ShuttleCalled, LogImpact.High,
|
||||
$"Shuttle called by {ToPrettyString(requester.Value):user}");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -183,8 +205,8 @@ namespace Content.Server.RoundEnd
|
||||
}
|
||||
|
||||
_chatSystem.DispatchGlobalAnnouncement(Loc.GetString(text,
|
||||
("time", time),
|
||||
("units", Loc.GetString(units))),
|
||||
("time", time),
|
||||
("units", Loc.GetString(units))),
|
||||
name,
|
||||
false,
|
||||
null,
|
||||
@@ -199,6 +221,8 @@ namespace Content.Server.RoundEnd
|
||||
ActivateCooldown();
|
||||
RaiseLocalEvent(RoundEndSystemChangedEvent.Default);
|
||||
|
||||
SendRoundStatus("shuttle_called");
|
||||
|
||||
var shuttle = _shuttle.GetShuttle();
|
||||
if (shuttle != null && TryComp<DeviceNetworkComponent>(shuttle, out var net))
|
||||
{
|
||||
@@ -208,25 +232,33 @@ namespace Content.Server.RoundEnd
|
||||
[ShuttleTimerMasks.SourceMap] = GetCentcomm(),
|
||||
[ShuttleTimerMasks.DestMap] = GetStation(),
|
||||
[ShuttleTimerMasks.ShuttleTime] = countdownTime,
|
||||
[ShuttleTimerMasks.SourceTime] = countdownTime + TimeSpan.FromSeconds(_shuttle.TransitTime + _cfg.GetCVar(CCVars.EmergencyShuttleDockTime)),
|
||||
[ShuttleTimerMasks.SourceTime] = countdownTime +
|
||||
TimeSpan.FromSeconds(_shuttle.TransitTime + _cfg.GetCVar(CCVars.EmergencyShuttleDockTime)),
|
||||
[ShuttleTimerMasks.DestTime] = countdownTime,
|
||||
};
|
||||
|
||||
_deviceNetworkSystem.QueuePacket(shuttle.Value, null, payload, net.TransmitFrequency);
|
||||
}
|
||||
}
|
||||
|
||||
public void CancelRoundEndCountdown(EntityUid? requester = null, bool checkCooldown = true)
|
||||
{
|
||||
if (_gameTicker.RunLevel != GameRunLevel.InRound) return;
|
||||
if (checkCooldown && _cooldownTokenSource != null) return;
|
||||
if (_gameTicker.RunLevel != GameRunLevel.InRound)
|
||||
return;
|
||||
|
||||
if (checkCooldown && _cooldownTokenSource != null)
|
||||
return;
|
||||
|
||||
if (_countdownTokenSource == null)
|
||||
return;
|
||||
|
||||
if (_countdownTokenSource == null) return;
|
||||
_countdownTokenSource.Cancel();
|
||||
_countdownTokenSource = null;
|
||||
|
||||
if (requester != null)
|
||||
{
|
||||
_adminLogger.Add(LogType.ShuttleRecalled, LogImpact.High, $"Shuttle recalled by {ToPrettyString(requester.Value):user}");
|
||||
_adminLogger.Add(LogType.ShuttleRecalled, LogImpact.High,
|
||||
$"Shuttle recalled by {ToPrettyString(requester.Value):user}");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -243,6 +275,10 @@ namespace Content.Server.RoundEnd
|
||||
ActivateCooldown();
|
||||
RaiseLocalEvent(RoundEndSystemChangedEvent.Default);
|
||||
|
||||
//WD-EDIT
|
||||
SendRoundStatus("shuttle_recalled");
|
||||
//WD-EDIT
|
||||
|
||||
// remove all active shuttle timers
|
||||
var zero = TimeSpan.Zero;
|
||||
var shuttle = _shuttle.GetShuttle();
|
||||
@@ -256,21 +292,36 @@ namespace Content.Server.RoundEnd
|
||||
[ShuttleTimerMasks.ShuttleTime] = zero,
|
||||
[ShuttleTimerMasks.SourceTime] = zero,
|
||||
[ShuttleTimerMasks.DestTime] = zero,
|
||||
[ShuttleTimerMasks.Text] = new string?[] { string.Empty, string.Empty }
|
||||
[ShuttleTimerMasks.Text] = new[] { string.Empty, string.Empty }
|
||||
};
|
||||
|
||||
_deviceNetworkSystem.QueuePacket(shuttle.Value, null, payload, net.TransmitFrequency);
|
||||
}
|
||||
}
|
||||
|
||||
//WD-EDIT
|
||||
private void SendRoundStatus(string status)
|
||||
{
|
||||
var utkaRoundStatusEvent = new UtkaRoundStatusEvent()
|
||||
{
|
||||
Message = status
|
||||
};
|
||||
|
||||
_utkaSocketWrapper.SendMessageToAll(utkaRoundStatusEvent);
|
||||
}
|
||||
//WD-EDIT
|
||||
|
||||
public void EndRound(TimeSpan? countdownTime = null)
|
||||
{
|
||||
if (_gameTicker.RunLevel != GameRunLevel.InRound) return;
|
||||
if (_gameTicker.RunLevel != GameRunLevel.InRound)
|
||||
return;
|
||||
|
||||
LastCountdownStart = null;
|
||||
ExpectedCountdownEnd = null;
|
||||
RaiseLocalEvent(RoundEndSystemChangedEvent.Default);
|
||||
_gameTicker.EndRound();
|
||||
_countdownTokenSource?.Cancel();
|
||||
_countdownTokenSource = new();
|
||||
_countdownTokenSource = new CancellationTokenSource();
|
||||
|
||||
countdownTime ??= TimeSpan.FromSeconds(_cfg.GetCVar(CCVars.RoundRestartTime));
|
||||
int time;
|
||||
@@ -285,11 +336,13 @@ namespace Content.Server.RoundEnd
|
||||
time = countdownTime.Value.Minutes;
|
||||
unitsLocString = "eta-units-minutes";
|
||||
}
|
||||
|
||||
_chatManager.DispatchServerAnnouncement(
|
||||
Loc.GetString(
|
||||
"round-end-system-round-restart-eta-announcement",
|
||||
("time", time),
|
||||
("units", Loc.GetString(unitsLocString))));
|
||||
|
||||
Timer.Spawn(countdownTime.Value, AfterEndRoundRestart, _countdownTokenSource.Token);
|
||||
}
|
||||
|
||||
@@ -301,7 +354,8 @@ namespace Content.Server.RoundEnd
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="textCall"></param>
|
||||
/// <param name="textAnnounce"></param>
|
||||
public void DoRoundEndBehavior(RoundEndBehavior behavior,
|
||||
public void DoRoundEndBehavior(
|
||||
RoundEndBehavior behavior,
|
||||
TimeSpan time,
|
||||
string sender = "comms-console-announcement-title-centcom",
|
||||
string textCall = "round-end-system-shuttle-called-announcement",
|
||||
@@ -325,13 +379,16 @@ namespace Content.Server.RoundEnd
|
||||
RequestRoundEnd(time, null, false, textCall,
|
||||
Loc.GetString(sender));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void AfterEndRoundRestart()
|
||||
{
|
||||
if (_gameTicker.RunLevel != GameRunLevel.PostRound) return;
|
||||
if (_gameTicker.RunLevel != GameRunLevel.PostRound)
|
||||
return;
|
||||
|
||||
Reset();
|
||||
_gameTicker.RestartRound();
|
||||
}
|
||||
@@ -351,8 +408,10 @@ namespace Content.Server.RoundEnd
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
// Check if we should auto-call.
|
||||
int mins = _autoCalledBefore ? _cfg.GetCVar(CCVars.EmergencyShuttleAutoCallExtensionTime)
|
||||
: _cfg.GetCVar(CCVars.EmergencyShuttleAutoCallTime);
|
||||
int mins = _autoCalledBefore
|
||||
? _cfg.GetCVar(CCVars.EmergencyShuttleAutoCallExtensionTime)
|
||||
: _cfg.GetCVar(CCVars.EmergencyShuttleAutoCallTime);
|
||||
|
||||
if (mins != 0 && _gameTiming.CurTime - AutoCallStartTime > TimeSpan.FromMinutes(mins))
|
||||
{
|
||||
if (!_shuttle.EmergencyShuttleArrived && ExpectedCountdownEnd is null)
|
||||
|
||||
@@ -234,6 +234,11 @@ public sealed partial class EmergencyShuttleSystem
|
||||
|
||||
_shuttle.AddFTLDestination(comp.Entity.Value, true);
|
||||
}
|
||||
|
||||
if (EarlyLaunchAuthorized)
|
||||
SendRoundStatus("shuttle_escaped");
|
||||
else
|
||||
SendRoundStatus("shuttle_left");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ using Content.Server.Shuttles.Components;
|
||||
using Content.Server.Shuttles.Events;
|
||||
using Content.Server.Station.Components;
|
||||
using Content.Server.Station.Systems;
|
||||
using Content.Server.UtkaIntegration;
|
||||
using Content.Shared.Access.Systems;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared.Database;
|
||||
@@ -62,6 +63,10 @@ public sealed partial class EmergencyShuttleSystem : EntitySystem
|
||||
[Dependency] private readonly TransformSystem _transformSystem = default!;
|
||||
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
|
||||
|
||||
//WD-EDIT
|
||||
[Dependency] private readonly UtkaTCPWrapper _utkaSocketWrapper = default!;
|
||||
//WD-EDIT
|
||||
|
||||
private ISawmill _sawmill = default!;
|
||||
|
||||
private const float ShuttleSpawnBuffer = 1f;
|
||||
@@ -185,6 +190,7 @@ public sealed partial class EmergencyShuttleSystem : EntitySystem
|
||||
if (config == null)
|
||||
return;
|
||||
|
||||
SendRoundStatus("shuttle_docked");
|
||||
RaiseNetworkEvent(new EmergencyShuttlePositionMessage()
|
||||
{
|
||||
StationUid = GetNetEntity(targetGrid),
|
||||
@@ -197,25 +203,25 @@ public sealed partial class EmergencyShuttleSystem : EntitySystem
|
||||
/// </summary>
|
||||
private void OnEmergencyFTL(EntityUid uid, EmergencyShuttleComponent component, ref FTLStartedEvent args)
|
||||
{
|
||||
TimeSpan ftlTime = TimeSpan.FromSeconds
|
||||
var ftlTime = TimeSpan.FromSeconds
|
||||
(
|
||||
TryComp<FTLComponent>(uid, out var ftlComp) ?
|
||||
ftlComp.TravelTime : ShuttleSystem.DefaultTravelTime
|
||||
TryComp<FTLComponent>(uid, out var ftlComp) ? ftlComp.TravelTime : ShuttleSystem.DefaultTravelTime
|
||||
);
|
||||
|
||||
if (TryComp<DeviceNetworkComponent>(uid, out var netComp))
|
||||
if (!TryComp<DeviceNetworkComponent>(uid, out var netComp))
|
||||
return;
|
||||
|
||||
var payload = new NetworkPayload
|
||||
{
|
||||
var payload = new NetworkPayload
|
||||
{
|
||||
[ShuttleTimerMasks.ShuttleMap] = uid,
|
||||
[ShuttleTimerMasks.SourceMap] = args.FromMapUid,
|
||||
[ShuttleTimerMasks.DestMap] = args.TargetCoordinates.GetMapUid(_entityManager),
|
||||
[ShuttleTimerMasks.ShuttleTime] = ftlTime,
|
||||
[ShuttleTimerMasks.SourceTime] = ftlTime,
|
||||
[ShuttleTimerMasks.DestTime] = ftlTime
|
||||
};
|
||||
_deviceNetworkSystem.QueuePacket(uid, null, payload, netComp.TransmitFrequency);
|
||||
}
|
||||
[ShuttleTimerMasks.ShuttleMap] = uid,
|
||||
[ShuttleTimerMasks.SourceMap] = args.FromMapUid,
|
||||
[ShuttleTimerMasks.DestMap] = args.TargetCoordinates.GetMapUid(_entityManager),
|
||||
[ShuttleTimerMasks.ShuttleTime] = ftlTime,
|
||||
[ShuttleTimerMasks.SourceTime] = ftlTime,
|
||||
[ShuttleTimerMasks.DestTime] = ftlTime
|
||||
};
|
||||
|
||||
_deviceNetworkSystem.QueuePacket(uid, null, payload, netComp.TransmitFrequency);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -225,20 +231,21 @@ public sealed partial class EmergencyShuttleSystem : EntitySystem
|
||||
{
|
||||
var countdownTime = TimeSpan.FromSeconds(_configManager.GetCVar(CCVars.RoundRestartTime));
|
||||
var shuttle = args.Entity;
|
||||
if (TryComp<DeviceNetworkComponent>(shuttle, out var net))
|
||||
if (!TryComp<DeviceNetworkComponent>(shuttle, out var net))
|
||||
return;
|
||||
|
||||
var payload = new NetworkPayload
|
||||
{
|
||||
var payload = new NetworkPayload
|
||||
{
|
||||
[ShuttleTimerMasks.ShuttleMap] = shuttle,
|
||||
[ShuttleTimerMasks.SourceMap] = _roundEnd.GetCentcomm(),
|
||||
[ShuttleTimerMasks.DestMap] = _roundEnd.GetStation(),
|
||||
[ShuttleTimerMasks.ShuttleTime] = countdownTime,
|
||||
[ShuttleTimerMasks.SourceTime] = countdownTime,
|
||||
[ShuttleTimerMasks.DestTime] = countdownTime,
|
||||
[ShuttleTimerMasks.Text] = new string?[] { "BYE!" }
|
||||
};
|
||||
_deviceNetworkSystem.QueuePacket(shuttle, null, payload, net.TransmitFrequency);
|
||||
}
|
||||
[ShuttleTimerMasks.ShuttleMap] = shuttle,
|
||||
[ShuttleTimerMasks.SourceMap] = _roundEnd.GetCentcomm(),
|
||||
[ShuttleTimerMasks.DestMap] = _roundEnd.GetStation(),
|
||||
[ShuttleTimerMasks.ShuttleTime] = countdownTime,
|
||||
[ShuttleTimerMasks.SourceTime] = countdownTime,
|
||||
[ShuttleTimerMasks.DestTime] = countdownTime,
|
||||
[ShuttleTimerMasks.Text] = new[] { "BYE!" }
|
||||
};
|
||||
|
||||
_deviceNetworkSystem.QueuePacket(shuttle, null, payload, net.TransmitFrequency);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -258,8 +265,12 @@ public sealed partial class EmergencyShuttleSystem : EntitySystem
|
||||
// UHH GOOD LUCK
|
||||
if (targetGrid == null)
|
||||
{
|
||||
_logger.Add(LogType.EmergencyShuttle, LogImpact.High, $"Emergency shuttle {ToPrettyString(stationUid)} unable to dock with station {ToPrettyString(stationUid)}");
|
||||
_chatSystem.DispatchStationAnnouncement(stationUid, Loc.GetString("emergency-shuttle-good-luck"), playDefaultSound: false);
|
||||
_logger.Add(LogType.EmergencyShuttle, LogImpact.High,
|
||||
$"Emergency shuttle {ToPrettyString(stationUid)} unable to dock with station {ToPrettyString(stationUid)}");
|
||||
|
||||
_chatSystem.DispatchStationAnnouncement(stationUid, Loc.GetString("emergency-shuttle-good-luck"),
|
||||
playDefaultSound: false);
|
||||
|
||||
// TODO: Need filter extensions or something don't blame me.
|
||||
_audio.PlayGlobal("/Audio/Misc/notice1.ogg", Filter.Broadcast(), true);
|
||||
return;
|
||||
@@ -271,8 +282,12 @@ public sealed partial class EmergencyShuttleSystem : EntitySystem
|
||||
{
|
||||
if (TryComp<TransformComponent>(targetGrid.Value, out var targetXform))
|
||||
{
|
||||
var angle = _dock.GetAngle(stationShuttle.EmergencyShuttle.Value, xform, targetGrid.Value, targetXform, xformQuery);
|
||||
_chatSystem.DispatchStationAnnouncement(stationUid, Loc.GetString("emergency-shuttle-docked", ("time", $"{_consoleAccumulator:0}"), ("direction", angle.GetDir())), playDefaultSound: false);
|
||||
var angle = _dock.GetAngle(stationShuttle.EmergencyShuttle.Value, xform, targetGrid.Value, targetXform,
|
||||
xformQuery);
|
||||
|
||||
_chatSystem.DispatchStationAnnouncement(stationUid,
|
||||
Loc.GetString("emergency-shuttle-docked", ("time", $"{_consoleAccumulator:0}"),
|
||||
("direction", angle.GetDir())), playDefaultSound: false);
|
||||
}
|
||||
|
||||
// shuttle timers
|
||||
@@ -289,10 +304,14 @@ public sealed partial class EmergencyShuttleSystem : EntitySystem
|
||||
[ShuttleTimerMasks.DestTime] = time + TimeSpan.FromSeconds(TransitTime),
|
||||
[ShuttleTimerMasks.Docked] = true
|
||||
};
|
||||
_deviceNetworkSystem.QueuePacket(stationShuttle.EmergencyShuttle.Value, null, payload, netComp.TransmitFrequency);
|
||||
|
||||
_deviceNetworkSystem.QueuePacket(stationShuttle.EmergencyShuttle.Value, null, payload,
|
||||
netComp.TransmitFrequency);
|
||||
}
|
||||
|
||||
_logger.Add(LogType.EmergencyShuttle, LogImpact.High, $"Emergency shuttle {ToPrettyString(stationUid)} docked with stations");
|
||||
_logger.Add(LogType.EmergencyShuttle, LogImpact.High,
|
||||
$"Emergency shuttle {ToPrettyString(stationUid)} docked with stations");
|
||||
|
||||
// TODO: Need filter extensions or something don't blame me.
|
||||
_audio.PlayGlobal("/Audio/Announcements/shuttle_dock.ogg", Filter.Broadcast(), true);
|
||||
}
|
||||
@@ -300,11 +319,16 @@ public sealed partial class EmergencyShuttleSystem : EntitySystem
|
||||
{
|
||||
if (TryComp<TransformComponent>(targetGrid.Value, out var targetXform))
|
||||
{
|
||||
var angle = _dock.GetAngle(stationShuttle.EmergencyShuttle.Value, xform, targetGrid.Value, targetXform, xformQuery);
|
||||
_chatSystem.DispatchStationAnnouncement(stationUid, Loc.GetString("emergency-shuttle-nearby", ("direction", angle.GetDir())), playDefaultSound: false);
|
||||
var angle = _dock.GetAngle(stationShuttle.EmergencyShuttle.Value, xform, targetGrid.Value, targetXform,
|
||||
xformQuery);
|
||||
|
||||
_chatSystem.DispatchStationAnnouncement(stationUid,
|
||||
Loc.GetString("emergency-shuttle-nearby", ("direction", angle.GetDir())), playDefaultSound: false);
|
||||
}
|
||||
|
||||
_logger.Add(LogType.EmergencyShuttle, LogImpact.High, $"Emergency shuttle {ToPrettyString(stationUid)} unable to find a valid docking port for {ToPrettyString(stationUid)}");
|
||||
_logger.Add(LogType.EmergencyShuttle, LogImpact.High,
|
||||
$"Emergency shuttle {ToPrettyString(stationUid)} unable to find a valid docking port for {ToPrettyString(stationUid)}");
|
||||
|
||||
// TODO: Need filter extensions or something don't blame me.
|
||||
_audio.PlayGlobal("/Audio/Misc/notice1.ogg", Filter.Broadcast(), true);
|
||||
}
|
||||
@@ -372,7 +396,9 @@ public sealed partial class EmergencyShuttleSystem : EntitySystem
|
||||
var query = AllEntityQuery<StationEmergencyShuttleComponent>();
|
||||
|
||||
while (query.MoveNext(out var uid, out var comp))
|
||||
{
|
||||
AddEmergencyShuttle(uid, comp);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddCentcomm(StationCentcommComponent component)
|
||||
@@ -409,10 +435,11 @@ public sealed partial class EmergencyShuttleSystem : EntitySystem
|
||||
}
|
||||
|
||||
var mapId = _mapManager.CreateMap();
|
||||
var grid = _map.LoadGrid(mapId, component.Map.ToString(), new MapLoadOptions()
|
||||
var grid = _map.LoadGrid(mapId, component.Map.ToString(), new MapLoadOptions
|
||||
{
|
||||
LoadMap = false,
|
||||
});
|
||||
|
||||
var map = _mapManager.GetMapEntityId(mapId);
|
||||
|
||||
if (!Exists(map))
|
||||
@@ -535,11 +562,26 @@ public sealed partial class EmergencyShuttleSystem : EntitySystem
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool IsOnGrid(TransformComponent xform, EntityUid shuttle, MapGridComponent? grid = null, TransformComponent? shuttleXform = null)
|
||||
private bool IsOnGrid(
|
||||
TransformComponent xform,
|
||||
EntityUid shuttle,
|
||||
MapGridComponent? grid = null,
|
||||
TransformComponent? shuttleXform = null)
|
||||
{
|
||||
if (!Resolve(shuttle, ref grid, ref shuttleXform))
|
||||
return false;
|
||||
|
||||
return _transformSystem.GetWorldMatrix(shuttleXform).TransformBox(grid.LocalAABB).Contains(_transformSystem.GetWorldPosition(xform));
|
||||
return _transformSystem.GetWorldMatrix(shuttleXform).TransformBox(grid.LocalAABB)
|
||||
.Contains(_transformSystem.GetWorldPosition(xform));
|
||||
}
|
||||
|
||||
private void SendRoundStatus(string status)
|
||||
{
|
||||
var utkaRoundStatusEvent = new UtkaRoundStatusEvent()
|
||||
{
|
||||
Message = status
|
||||
};
|
||||
|
||||
_utkaSocketWrapper.SendMessageToAll(utkaRoundStatusEvent);
|
||||
}
|
||||
}
|
||||
|
||||
11
Content.Server/UtkaIntegration/Commands/IUtkaCommand.cs
Normal file
11
Content.Server/UtkaIntegration/Commands/IUtkaCommand.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using System.Net;
|
||||
using Content.Server.UtkaIntegration.TCP;
|
||||
|
||||
namespace Content.Server.UtkaIntegration;
|
||||
|
||||
public interface IUtkaCommand
|
||||
{
|
||||
string Name { get; }
|
||||
Type RequestMessageType { get; }
|
||||
public void Execute(UtkaTCPSession session, UtkaBaseMessage baseMessage);
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using Content.Server.Administration.Managers;
|
||||
using Content.Server.UtkaIntegration.TCP;
|
||||
using Content.Shared.CCVar;
|
||||
using Robust.Shared;
|
||||
using Robust.Shared.Configuration;
|
||||
|
||||
namespace Content.Server.UtkaIntegration;
|
||||
|
||||
public sealed class UtkaAdminWhoCommand : IUtkaCommand
|
||||
{
|
||||
public string Name => "adminwho";
|
||||
public Type RequestMessageType => typeof(UtkaAdminWhoRequest);
|
||||
|
||||
[Dependency] private readonly UtkaTCPWrapper _utkaSocketWrapper = default!;
|
||||
|
||||
public void Execute(UtkaTCPSession session, UtkaBaseMessage baseMessage)
|
||||
{
|
||||
if(baseMessage is not UtkaAdminWhoRequest message) return;
|
||||
IoCManager.InjectDependencies(this);
|
||||
|
||||
var adminManager = IoCManager.Resolve<IAdminManager>();
|
||||
|
||||
var admins = adminManager.ActiveAdmins.ToList();
|
||||
|
||||
var adminsList = new List<string>();
|
||||
|
||||
foreach (var admin in admins)
|
||||
{
|
||||
adminsList.Add(admin.Name);
|
||||
}
|
||||
|
||||
var toUtkaMessage = new UtkaAdminWhoResponse()
|
||||
{
|
||||
Admins = adminsList
|
||||
};
|
||||
|
||||
_utkaSocketWrapper.SendMessageToAll(toUtkaMessage);
|
||||
}
|
||||
}
|
||||
29
Content.Server/UtkaIntegration/Commands/UtkaAssayCommand.cs
Normal file
29
Content.Server/UtkaIntegration/Commands/UtkaAssayCommand.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using Content.Server.Administration.Managers;
|
||||
using Content.Server.Chat.Managers;
|
||||
using Content.Server.UtkaIntegration.TCP;
|
||||
using Content.Shared.Chat;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Server.UtkaIntegration;
|
||||
|
||||
public sealed class UtkaAssayCommand : IUtkaCommand
|
||||
{
|
||||
public string Name => "asay";
|
||||
public Type RequestMessageType => typeof(UtkaAsayRequest);
|
||||
|
||||
public void Execute(UtkaTCPSession session, UtkaBaseMessage baseMessage)
|
||||
{
|
||||
if(baseMessage is not UtkaAsayRequest message) return;
|
||||
|
||||
var ckey = message.ACkey;
|
||||
|
||||
if(string.IsNullOrWhiteSpace(message.Message) || string.IsNullOrWhiteSpace(ckey)) return;
|
||||
|
||||
var chatManager = IoCManager.Resolve<IChatManager>();
|
||||
|
||||
chatManager.SendHookAdminChat(ckey, message.Message);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
using Content.Server.UtkaIntegration.TCP;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared.White;
|
||||
using Robust.Shared.Configuration;
|
||||
|
||||
namespace Content.Server.UtkaIntegration;
|
||||
|
||||
public sealed class UtkaAuthenticationCommand : IUtkaCommand
|
||||
{
|
||||
[Dependency] private readonly IConfigurationManager _configurationManager = default!;
|
||||
[Dependency] private readonly UtkaTCPWrapper _utkaTcpWrapper = default!;
|
||||
|
||||
public string Name => "handshake";
|
||||
public Type RequestMessageType => typeof(UtkaHandshakeMessage);
|
||||
|
||||
public void Execute(UtkaTCPSession session, UtkaBaseMessage baseMessage)
|
||||
{
|
||||
if (baseMessage is not UtkaHandshakeMessage message)
|
||||
return;
|
||||
|
||||
IoCManager.InjectDependencies(this);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(message.Key))
|
||||
{
|
||||
SendMessage(session, "key_missmatch");
|
||||
return;
|
||||
}
|
||||
|
||||
var key = _configurationManager.GetCVar(WhiteCVars.UtkaSocketKey);
|
||||
|
||||
if (key != message.Key)
|
||||
{
|
||||
SendMessage(session, "key_missmatch");
|
||||
return;
|
||||
}
|
||||
|
||||
if (session.Authenticated)
|
||||
{
|
||||
SendMessage(session, "already_authentificated");
|
||||
return;
|
||||
}
|
||||
|
||||
session.Authenticated = true;
|
||||
SendMessage(session, "handshake_accepted");
|
||||
}
|
||||
|
||||
private void SendMessage(UtkaTCPSession session, string message)
|
||||
{
|
||||
var response = new UtkaHandshakeMessage()
|
||||
{
|
||||
Key = _configurationManager.GetCVar(WhiteCVars.UtkaSocketKey),
|
||||
Message = message
|
||||
};
|
||||
|
||||
_utkaTcpWrapper.SendMessageToClient(session, response);
|
||||
}
|
||||
}
|
||||
36
Content.Server/UtkaIntegration/Commands/UtkaPmCommand.cs
Normal file
36
Content.Server/UtkaIntegration/Commands/UtkaPmCommand.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using Content.Server.Administration.Systems;
|
||||
using Content.Server.UtkaIntegration.TCP;
|
||||
using Robust.Server.Player;
|
||||
|
||||
namespace Content.Server.UtkaIntegration;
|
||||
|
||||
public sealed class UtkaPmCommand : IUtkaCommand
|
||||
{
|
||||
public string Name => "discord_pm";
|
||||
public Type RequestMessageType => typeof(UtkaPmRequest);
|
||||
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
[Dependency] private UtkaTCPWrapper _utkaSocketWrapper = default!;
|
||||
|
||||
public void Execute(UtkaTCPSession session, UtkaBaseMessage baseMessage)
|
||||
{
|
||||
if(baseMessage is not UtkaPmRequest message) return;
|
||||
var _bwoink = EntitySystem.Get<BwoinkSystem>();
|
||||
IoCManager.InjectDependencies(this);
|
||||
|
||||
if(string.IsNullOrWhiteSpace(message.Message) || string.IsNullOrWhiteSpace(message.Sender) || string.IsNullOrWhiteSpace(message.Reciever)) return;
|
||||
|
||||
var toUtkaMessage = new UtkaPmResponse();
|
||||
if (!_playerManager.TryGetUserId(message.Reciever, out var reciever))
|
||||
{
|
||||
toUtkaMessage.Message = false;
|
||||
_utkaSocketWrapper.SendMessageToAll(toUtkaMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
_bwoink.SendUtkaBwoinkMessage(reciever, message.Sender, message.Message);
|
||||
|
||||
toUtkaMessage.Message = true;
|
||||
_utkaSocketWrapper.SendMessageToAll(toUtkaMessage);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System.Net;
|
||||
using Content.Server.Chat.Managers;
|
||||
using Content.Server.UtkaIntegration.TCP;
|
||||
|
||||
namespace Content.Server.UtkaIntegration;
|
||||
|
||||
public sealed class UtkaSendOOCMessage : IUtkaCommand
|
||||
{
|
||||
public string Name => "ooc";
|
||||
public Type RequestMessageType => typeof(UtkaOOCRequest);
|
||||
|
||||
public void Execute(UtkaTCPSession session, UtkaBaseMessage baseMessage)
|
||||
{
|
||||
if (baseMessage is not UtkaOOCRequest message) return;
|
||||
if(string.IsNullOrWhiteSpace(message.Message) || string.IsNullOrWhiteSpace(message.CKey)) return;
|
||||
|
||||
|
||||
var chatSystem = IoCManager.Resolve<IChatManager>();
|
||||
chatSystem.SendHookOOC($"{message.CKey}", $"{message.Message}");
|
||||
}
|
||||
}
|
||||
85
Content.Server/UtkaIntegration/Commands/UtkaStatusCommand.cs
Normal file
85
Content.Server/UtkaIntegration/Commands/UtkaStatusCommand.cs
Normal file
@@ -0,0 +1,85 @@
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using Content.Server.Administration.Managers;
|
||||
using Content.Server.AlertLevel;
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Server.Maps;
|
||||
using Content.Server.RoundEnd;
|
||||
using Content.Server.Station.Systems;
|
||||
using Content.Server.UtkaIntegration.TCP;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.Player;
|
||||
|
||||
namespace Content.Server.UtkaIntegration;
|
||||
|
||||
public sealed class UtkaStatusCommand : IUtkaCommand
|
||||
{
|
||||
public string Name => "status";
|
||||
public Type RequestMessageType => typeof(UtkaStatusRequsets);
|
||||
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly IAdminManager _adminManager = default!;
|
||||
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||
[Dependency] private readonly UtkaTCPWrapper _utkaSocketWrapper = default!;
|
||||
[Dependency] private readonly IEntityManager _entMan = default!;
|
||||
[Dependency] private readonly IGameMapManager _gameMapManager = default!;
|
||||
|
||||
public void Execute(UtkaTCPSession session, UtkaBaseMessage baseMessage)
|
||||
{
|
||||
if(baseMessage is not UtkaStatusRequsets message) return;
|
||||
var _gameTicker = EntitySystem.Get<GameTicker>();
|
||||
var _roundEndSystem = EntitySystem.Get<RoundEndSystem>();
|
||||
var _station = EntitySystem.Get<StationSystem>();
|
||||
IoCManager.InjectDependencies(this);
|
||||
|
||||
|
||||
var players = Filter.GetAllPlayers().ToList().Count;
|
||||
|
||||
var admins = _adminManager.ActiveAdmins.Select(x => x.Name).ToList().Count;
|
||||
|
||||
string shuttleData = string.Empty;
|
||||
|
||||
if (_roundEndSystem.ExpectedCountdownEnd == null)
|
||||
{
|
||||
shuttleData = "idle";
|
||||
}
|
||||
else
|
||||
{
|
||||
shuttleData = "called";
|
||||
}
|
||||
|
||||
var roundDuration = _gameTicker.RoundDuration().TotalSeconds;
|
||||
|
||||
string? gameMap = null;
|
||||
string? stationCode = null;
|
||||
foreach (var station in _station.Stations)
|
||||
{
|
||||
if (!_entMan.TryGetComponent(station, out AlertLevelComponent? alert) || stationCode != null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (alert is { CurrentLevel: { } })
|
||||
{
|
||||
stationCode = alert.CurrentLevel;
|
||||
|
||||
var map = _gameMapManager.GetSelectedMap();
|
||||
gameMap = map?.MapName ?? Loc.GetString("discord-round-unknown-map");
|
||||
}
|
||||
}
|
||||
|
||||
var toUtkaMessage = new UtkaStatusResponse()
|
||||
{
|
||||
Players = players,
|
||||
Admins = admins,
|
||||
Map = gameMap,
|
||||
ShuttleStatus = shuttleData,
|
||||
RoundDuration = roundDuration,
|
||||
StationCode = stationCode
|
||||
};
|
||||
|
||||
_utkaSocketWrapper.SendMessageToAll(toUtkaMessage);
|
||||
}
|
||||
}
|
||||
40
Content.Server/UtkaIntegration/Commands/UtkaWhoCommand.cs
Normal file
40
Content.Server/UtkaIntegration/Commands/UtkaWhoCommand.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using Content.Server.UtkaIntegration.TCP;
|
||||
using Content.Shared.CCVar;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.Player;
|
||||
|
||||
namespace Content.Server.UtkaIntegration;
|
||||
|
||||
public sealed class UtkaWhoCommand : IUtkaCommand
|
||||
{
|
||||
public string Name => "who";
|
||||
public Type RequestMessageType => typeof(UtkaWhoRequest);
|
||||
|
||||
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||
[Dependency] private UtkaTCPWrapper _utkaSocketWrapper = default!;
|
||||
|
||||
public void Execute(UtkaTCPSession session, UtkaBaseMessage baseMessage)
|
||||
{
|
||||
if(baseMessage is not UtkaWhoRequest _) return;
|
||||
|
||||
IoCManager.InjectDependencies(this);
|
||||
|
||||
var players = Filter.GetAllPlayers().ToList();
|
||||
var playerNames = players
|
||||
.Where(player => player.Status != SessionStatus.Disconnected)
|
||||
.Select(x => x.Name);
|
||||
|
||||
var toUtkaMessage = new UtkaWhoResponse()
|
||||
{
|
||||
Players = playerNames.ToList()
|
||||
};
|
||||
|
||||
_utkaSocketWrapper.SendMessageToAll(toUtkaMessage);
|
||||
}
|
||||
}
|
||||
113
Content.Server/UtkaIntegration/TCP/UtkaTCPServer.cs
Normal file
113
Content.Server/UtkaIntegration/TCP/UtkaTCPServer.cs
Normal file
@@ -0,0 +1,113 @@
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.UtkaIntegration.TCP;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared.White;
|
||||
using NetCoreServer;
|
||||
using Robust.Shared.Asynchronous;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Timing;
|
||||
using YamlDotNet.Core.Tokens;
|
||||
using Timer = Robust.Shared.Timing.Timer;
|
||||
|
||||
namespace Content.Server.UtkaIntegration;
|
||||
|
||||
public sealed class UtkaTCPServer : TcpServer
|
||||
{
|
||||
|
||||
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||
[Dependency] private readonly ITaskManager _taskManager = default!;
|
||||
[Dependency] private readonly ITimerManager _timerManager = default!;
|
||||
|
||||
public static readonly Dictionary<string, IUtkaCommand> Commands = new();
|
||||
private List<UtkaTCPSession> _authenticatedSessions = new();
|
||||
|
||||
private string? _key;
|
||||
|
||||
protected override TcpSession CreateSession() { return new UtkaTCPSession(this); }
|
||||
public UtkaTCPServer(IPAddress address, int port) : base(address, port)
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
_cfg.OnValueChanged(WhiteCVars.UtkaSocketKey, key => _key = key, true);
|
||||
OptionKeepAlive = true;
|
||||
}
|
||||
|
||||
public void SendMessageToAll(UtkaBaseMessage message)
|
||||
{
|
||||
foreach (var session in Sessions.Values.Cast<UtkaTCPSession>())
|
||||
{
|
||||
if(!session.Authenticated) continue;
|
||||
|
||||
session.SendAsync(JsonSerializer.Serialize(message, message.GetType()));
|
||||
}
|
||||
}
|
||||
|
||||
public void SendMessageToClient(UtkaTCPSession session, UtkaBaseMessage message)
|
||||
{
|
||||
session.SendAsync(JsonSerializer.Serialize(message, message.GetType()));
|
||||
}
|
||||
|
||||
protected override void OnConnected(TcpSession session)
|
||||
{
|
||||
var utkaSession = (UtkaTCPSession) session;
|
||||
var cancellationToken = new CancellationTokenSource();
|
||||
|
||||
utkaSession.OnMessageReceived += (sender, message) =>
|
||||
{
|
||||
ExecuteCommand(utkaSession, message);
|
||||
};
|
||||
|
||||
var autoDisconnectionTimer = new Timer(25000, false, () =>
|
||||
{
|
||||
if (!utkaSession.Authenticated)
|
||||
{
|
||||
utkaSession.Disconnect();
|
||||
}
|
||||
});
|
||||
|
||||
_timerManager.AddTimer(autoDisconnectionTimer, cancellationToken.Token);
|
||||
}
|
||||
|
||||
protected override void OnDisconnecting(TcpSession session)
|
||||
{
|
||||
_authenticatedSessions.Remove((session as UtkaTCPSession)!);
|
||||
base.OnDisconnecting(session);
|
||||
}
|
||||
|
||||
protected override void OnError(SocketError error)
|
||||
{
|
||||
}
|
||||
private void ExecuteCommand(UtkaTCPSession session, UtkaBaseMessage fromUtkaMessage)
|
||||
{
|
||||
var command = fromUtkaMessage.Command!;
|
||||
|
||||
if (!Commands.ContainsKey(command))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_taskManager.RunOnMainThread(() => Commands[command].Execute(session, fromUtkaMessage));
|
||||
}
|
||||
|
||||
public static void RegisterCommands()
|
||||
{
|
||||
var assembly = Assembly.GetExecutingAssembly();
|
||||
var types = assembly.GetTypes();
|
||||
|
||||
var commands = types.Where(type => typeof(IUtkaCommand).IsAssignableFrom(type) && type.GetInterfaces().Contains(typeof(IUtkaCommand))).ToList();
|
||||
|
||||
foreach (var command in commands)
|
||||
{
|
||||
if (Activator.CreateInstance(command) is IUtkaCommand utkaCommand)
|
||||
{
|
||||
Commands[utkaCommand.Name] = utkaCommand;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
81
Content.Server/UtkaIntegration/TCP/UtkaTCPSession.cs
Normal file
81
Content.Server/UtkaIntegration/TCP/UtkaTCPSession.cs
Normal file
@@ -0,0 +1,81 @@
|
||||
using System.Linq;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using NetCoreServer;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Content.Server.UtkaIntegration.TCP;
|
||||
|
||||
public sealed class UtkaTCPSession : TcpSession
|
||||
{
|
||||
public event EventHandler<UtkaBaseMessage>? OnMessageReceived;
|
||||
|
||||
public bool Authenticated { get; set; }
|
||||
|
||||
public UtkaTCPSession(TcpServer server) : base(server)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnReceived(byte[] buffer, long offset, long size)
|
||||
{
|
||||
if (!ValidateMessage(buffer, offset, size, out var message))
|
||||
{
|
||||
this.SendAsync("Validation fail");
|
||||
return;
|
||||
}
|
||||
|
||||
OnMessageReceived?.Invoke(this, message!);
|
||||
}
|
||||
|
||||
protected override void OnError(SocketError error)
|
||||
{
|
||||
SendAsync($"{error.ToString()}");
|
||||
base.OnError(error);
|
||||
}
|
||||
|
||||
protected override void OnConnected()
|
||||
{
|
||||
SendAsync("Hello from грабли, знай утка я ебал тебя в зад!!!");
|
||||
base.OnConnected();
|
||||
}
|
||||
|
||||
private bool ValidateMessage(byte[] buffer, long offset, long size, out UtkaBaseMessage? fromDiscordMessage)
|
||||
{
|
||||
var message = Encoding.UTF8.GetString(buffer, (int) offset, (int) size);
|
||||
fromDiscordMessage = null;
|
||||
|
||||
if (string.IsNullOrEmpty(message))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var commandName = JObject.Parse(message)["command"];
|
||||
if (commandName == null)
|
||||
return false;
|
||||
|
||||
var utkaCommand = UtkaTCPServer.Commands.Values.FirstOrDefault(x => x.Name == commandName.ToString());
|
||||
|
||||
if (utkaCommand == null)
|
||||
return false;
|
||||
|
||||
var messageType = utkaCommand.RequestMessageType;
|
||||
|
||||
try
|
||||
{
|
||||
fromDiscordMessage = JsonSerializer.Deserialize(message, messageType) as UtkaBaseMessage;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void OnDisconnected()
|
||||
{
|
||||
base.OnDisconnecting();
|
||||
Dispose();
|
||||
}
|
||||
}
|
||||
64
Content.Server/UtkaIntegration/TCP/UtkaTCPWrapper.cs
Normal file
64
Content.Server/UtkaIntegration/TCP/UtkaTCPWrapper.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
using System.Net;
|
||||
using Content.Server.UtkaIntegration.TCP;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared.White;
|
||||
using Robust.Shared;
|
||||
using Robust.Shared.Configuration;
|
||||
|
||||
namespace Content.Server.UtkaIntegration;
|
||||
|
||||
public sealed class UtkaTCPWrapper
|
||||
{
|
||||
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||
|
||||
private UtkaTCPServer _server = default!;
|
||||
private string _key = string.Empty;
|
||||
|
||||
private bool _initialized;
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
if(_initialized) return;
|
||||
|
||||
_key = _cfg.GetCVar(WhiteCVars.UtkaSocketKey);
|
||||
|
||||
if (string.IsNullOrEmpty(_key))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var port = _cfg.GetCVar(CVars.NetPort) + 100;
|
||||
|
||||
try
|
||||
{
|
||||
_server = new UtkaTCPServer(IPAddress.Any, port);
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_server.Start();
|
||||
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
public void SendMessageToAll(UtkaBaseMessage message)
|
||||
{
|
||||
_server.SendMessageToAll(message);
|
||||
}
|
||||
|
||||
public void SendMessageToClient(UtkaTCPSession session, UtkaBaseMessage message)
|
||||
{
|
||||
_server.SendMessageToClient(session, message);
|
||||
}
|
||||
|
||||
public void Shutdown()
|
||||
{
|
||||
_server.Stop();
|
||||
_server.Multicast("Server shutting down.");
|
||||
_server.DisconnectAll();
|
||||
_server.Dispose();
|
||||
}
|
||||
}
|
||||
172
Content.Server/UtkaIntegration/UtkaCommunication.cs
Normal file
172
Content.Server/UtkaIntegration/UtkaCommunication.cs
Normal file
@@ -0,0 +1,172 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Content.Server.UtkaIntegration;
|
||||
|
||||
public class UtkaBaseMessage
|
||||
{
|
||||
[JsonPropertyName("command")]
|
||||
public virtual string? Command { get; set; }
|
||||
}
|
||||
|
||||
public class UtkaHandshakeMessage : UtkaBaseMessage
|
||||
{
|
||||
[JsonPropertyName("command")]
|
||||
public override string Command => "handshake";
|
||||
|
||||
[JsonPropertyName("key")]
|
||||
public string? Key { get; set; }
|
||||
|
||||
[JsonPropertyName("message")]
|
||||
public string? Message { get; set; }
|
||||
}
|
||||
|
||||
public class UtkaOOCRequest : UtkaBaseMessage
|
||||
{
|
||||
[JsonPropertyName("command")]
|
||||
public override string? Command => "ooc";
|
||||
|
||||
[JsonPropertyName("ckey")]
|
||||
public string? CKey { get; set; }
|
||||
|
||||
[JsonPropertyName("message")]
|
||||
public string? Message { get; set; }
|
||||
}
|
||||
|
||||
public class UtkaAsayRequest : UtkaBaseMessage
|
||||
{
|
||||
[JsonPropertyName("command")]
|
||||
public override string? Command => "asay";
|
||||
|
||||
[JsonPropertyName("a_ckey")]
|
||||
public string? ACkey { get; set; }
|
||||
|
||||
[JsonPropertyName("message")]
|
||||
public string? Message { get; set; }
|
||||
}
|
||||
|
||||
public class UtkaPmRequest : UtkaBaseMessage
|
||||
{
|
||||
[JsonPropertyName("command")]
|
||||
public override string? Command => "discord_pm";
|
||||
|
||||
[JsonPropertyName("sender")]
|
||||
public string? Sender { get; set; }
|
||||
|
||||
[JsonPropertyName("receiver")]
|
||||
public string? Reciever { get; set; }
|
||||
|
||||
[JsonPropertyName("message")]
|
||||
public string? Message { get; set; }
|
||||
}
|
||||
|
||||
public class UtkaPmResponse : UtkaBaseMessage
|
||||
{
|
||||
[JsonPropertyName("command")]
|
||||
public override string? Command => "discord_pm";
|
||||
|
||||
[JsonPropertyName("message")]
|
||||
public bool? Message { get; set; }
|
||||
}
|
||||
|
||||
public class UtkaWhoRequest : UtkaBaseMessage
|
||||
{
|
||||
[JsonPropertyName("command")]
|
||||
public override string? Command => "who";
|
||||
}
|
||||
|
||||
public class UtkaWhoResponse : UtkaBaseMessage
|
||||
{
|
||||
[JsonPropertyName("command")]
|
||||
public override string? Command => "who";
|
||||
|
||||
[JsonPropertyName("players")]
|
||||
public List<string>? Players { get; set; }
|
||||
}
|
||||
|
||||
public class UtkaAdminWhoRequest : UtkaBaseMessage
|
||||
{
|
||||
[JsonPropertyName("command")]
|
||||
public override string? Command => "adminwho";
|
||||
}
|
||||
|
||||
public class UtkaAdminWhoResponse : UtkaBaseMessage
|
||||
{
|
||||
[JsonPropertyName("command")]
|
||||
public override string? Command => "adminwho";
|
||||
|
||||
[JsonPropertyName("admins")]
|
||||
public List<string>? Admins { get; set; }
|
||||
}
|
||||
|
||||
public class UtkaStatusRequsets : UtkaBaseMessage
|
||||
{
|
||||
[JsonPropertyName("command")]
|
||||
public override string? Command => "status";
|
||||
}
|
||||
|
||||
public class UtkaStatusResponse : UtkaBaseMessage
|
||||
{
|
||||
[JsonPropertyName("command")]
|
||||
public override string? Command => "status";
|
||||
|
||||
[JsonPropertyName("players")]
|
||||
public int? Players { get; set; }
|
||||
|
||||
[JsonPropertyName("admins")]
|
||||
public int? Admins { get; set; }
|
||||
|
||||
[JsonPropertyName("map")]
|
||||
public string? Map { get; set; }
|
||||
|
||||
[JsonPropertyName("round_duration")]
|
||||
public double RoundDuration { get; set; }
|
||||
|
||||
[JsonPropertyName("shuttle_status")]
|
||||
public string? ShuttleStatus { get; set; }
|
||||
|
||||
[JsonPropertyName("station_code")]
|
||||
public string? StationCode { get; set; }
|
||||
}
|
||||
|
||||
public class UtkaRoundstatusUpdate : UtkaBaseMessage
|
||||
{
|
||||
[JsonPropertyName("command")]
|
||||
public override string? Command => "roundstatus";
|
||||
|
||||
[JsonPropertyName("message")]
|
||||
public string? Message { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public sealed class UtkaChatEventMessage : UtkaBaseMessage
|
||||
{
|
||||
[JsonPropertyName("ckey")]
|
||||
public string? Ckey { get; set; }
|
||||
|
||||
[JsonPropertyName("message")]
|
||||
public string? Message { get; set; }
|
||||
}
|
||||
|
||||
public sealed class UtkaRoundStatusEvent : UtkaBaseMessage
|
||||
{
|
||||
[JsonPropertyName("command")]
|
||||
public override string? Command => "roundstatus";
|
||||
|
||||
[JsonPropertyName("message")]
|
||||
public string? Message { get; set; }
|
||||
}
|
||||
|
||||
public sealed class UtkaChatMeEvent : UtkaBaseMessage
|
||||
{
|
||||
[JsonPropertyName("command")]
|
||||
public override string? Command => "me";
|
||||
|
||||
[JsonPropertyName("ckey")]
|
||||
public string? Ckey { get; set; }
|
||||
|
||||
[JsonPropertyName("message")]
|
||||
public string? Message { get; set; }
|
||||
|
||||
[JsonPropertyName("character_name")]
|
||||
public string? CharacterName { get; set; }
|
||||
}
|
||||
@@ -1166,7 +1166,7 @@ namespace Content.Shared.CCVar
|
||||
/// <summary>
|
||||
/// If true, whenever OOC is disabled the Discord OOC relay will also be disabled.
|
||||
/// </summary>
|
||||
public static readonly CVarDef<bool> DisablingOOCDisablesRelay = CVarDef.Create("ooc.disabling_ooc_disables_relay", true, CVar.SERVERONLY);
|
||||
public static readonly CVarDef<bool> DisableHookedOOC = CVarDef.Create("ooc.disabling_ooc_disables_relay", false, CVar.SERVERONLY); //WD-EDIT
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not OOC chat should be enabled during a round.
|
||||
@@ -1361,6 +1361,12 @@ namespace Content.Shared.CCVar
|
||||
public static readonly CVarDef<bool> ArrivalsReturns =
|
||||
CVarDef.Create("shuttle.arrivals_returns", false, CVar.SERVERONLY);
|
||||
|
||||
/// <summary>
|
||||
/// Whether cargo shuttles are enabled.
|
||||
/// </summary>
|
||||
public static readonly CVarDef<bool> CargoShuttles =
|
||||
CVarDef.Create("shuttle.cargo", true, CVar.SERVERONLY);
|
||||
|
||||
/// <summary>
|
||||
/// Whether to automatically spawn escape shuttles.
|
||||
/// </summary>
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Content.Shared.White;
|
||||
/*
|
||||
* PUT YOUR CUSTOM VARS HERE
|
||||
* DO IT OR I WILL KILL YOU
|
||||
* with love, by Hail-Rakes
|
||||
* with love, by hailrakes
|
||||
*/
|
||||
|
||||
|
||||
@@ -56,4 +56,10 @@ public sealed class WhiteCVars
|
||||
public static readonly CVarDef<bool> DiscordRoundStartOnly =
|
||||
CVarDef.Create("discord.round_start_only", false, CVar.SERVERONLY);
|
||||
|
||||
/*
|
||||
* Sockets
|
||||
*/
|
||||
|
||||
public static readonly CVarDef<string> UtkaSocketKey = CVarDef.Create("utka.socket_key", "ass", CVar.SERVERONLY | CVar.CONFIDENTIAL);
|
||||
|
||||
}
|
||||
|
||||
@@ -71,6 +71,7 @@ SERVER_CONTENT_ASSEMBLIES = [
|
||||
SERVER_EXTRA_ASSEMBLIES = [
|
||||
"Npgsql.",
|
||||
"Microsoft",
|
||||
"NetCoreServer"
|
||||
]
|
||||
|
||||
SERVER_NOT_EXTRA_ASSEMBLIES = [
|
||||
|
||||
Reference in New Issue
Block a user