[feat] Stalin manager

# Conflicts:
#	Content.Client/Entry/EntryPoint.cs
#	Content.Server/Entry/EntryPoint.cs
#	Content.Server/GameTicking/Commands/JoinGameCommand.cs
#	Content.Server/GameTicking/GameTicker.Lobby.cs
#	Content.Server/GameTicking/GameTicker.RoundFlow.cs
#	Content.Server/GameTicking/GameTicker.Spawning.cs
This commit is contained in:
rhailrake
2023-04-27 21:56:22 +06:00
committed by Remuchi
parent 976b6788a8
commit c41e58fa3e
22 changed files with 539 additions and 10 deletions

View File

@@ -22,7 +22,7 @@ namespace Content.Client.Administration.Systems
// Currently this is only the ViewVariables verb, but more admin-UI related verbs can be added here.
// View variables verbs
if (_clientConGroupController.CanViewVar())
if (_clientConGroupController.CanAdminMenu())
{
var verb = new VvVerb()
{

View File

@@ -278,7 +278,7 @@ namespace Content.Client.Administration.UI
editButton.OnPressed += _ => OnEditRankPressed(kv);
_menu.AdminRanksList.AddChild(editButton);
if (!_adminManager.HasFlag(rank.Flags))
if (rank.Flags != AdminFlags.Host && !_adminManager.HasFlag(AdminFlags.Permissions) || rank.Flags == AdminFlags.Host && !_adminManager.HasFlag(AdminFlags.Host))
{
editButton.Disabled = true;
editButton.ToolTip = Loc.GetString("permissions-eui-do-not-have-required-flags-to-edit-rank-tooltip");
@@ -401,7 +401,15 @@ namespace Content.Client.Administration.UI
{
// Can only grant out perms you also have yourself.
// Primarily intended to prevent people giving themselves +HOST with +PERMISSIONS but generalized.
var disable = !ui._adminManager.HasFlag(flag);
bool disable;
if (flag != AdminFlags.Host)
{
disable = !ui._adminManager.HasFlag(AdminFlags.Permissions);
}
else
{
disable = !ui._adminManager.HasFlag(AdminFlags.Host);
}
var flagName = flag.ToString().ToUpper();
var group = new ButtonGroup();

View File

@@ -24,6 +24,7 @@ using Content.Client.Voting;
using Content.Client.White.JoinQueue;
using Content.Client.White.Sponsors;
using Content.Shared.Ame;
using Content.Client.White.Stalin;
using Content.Shared.Gravity;
using Content.Shared.Localizations;
using Robust.Client;
@@ -76,6 +77,7 @@ namespace Content.Client.Entry
//WD-EDIT
[Dependency] private readonly SponsorsManager _sponsorsManager = default!;
[Dependency] private readonly JoinQueueManager _queueManager = default!;
[Dependency] private readonly StalinManager _stalinManager = default!;
//WD-EDIT
public override void Init()
@@ -140,6 +142,10 @@ namespace Content.Client.Entry
_jobRequirements.Initialize();
_playbackMan.Initialize();
//WD-EDIT
_stalinManager.Initialize();
//WD-EDIT
//AUTOSCALING default Setup!
_configManager.SetCVar("interface.resolutionAutoScaleUpperCutoffX", 1080);
_configManager.SetCVar("interface.resolutionAutoScaleUpperCutoffY", 720);

View File

@@ -1,6 +1,7 @@
using Content.Client.Changelog;
using Content.Client.UserInterface.Systems.EscapeMenu;
using Content.Client.UserInterface.Systems.Guidebook;
using Content.Client.White.Stalin;
using Content.Shared.CCVar;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
@@ -11,12 +12,14 @@ namespace Content.Client.Info
{
public sealed class LinkBanner : BoxContainer
{
[Dependency] private readonly StalinManager _stalinManager = default!;
private readonly IConfigurationManager _cfg;
private ValueList<(CVarDef<string> cVar, Button button)> _infoLinks;
public LinkBanner()
{
IoCManager.InjectDependencies(this);
var buttons = new BoxContainer
{
Orientation = LayoutOrientation.Horizontal
@@ -54,6 +57,15 @@ namespace Content.Client.Info
buttons.AddChild(button);
_infoLinks.Add((cVar, button));
}
var saltedYaycaButton = new Button() {Text = "Привязать дискорд"};
saltedYaycaButton.OnPressed += _ =>
{
_stalinManager.RequestUri();
};
buttons.AddChild(saltedYaycaButton);
}
protected override void EnteredTree()

View File

@@ -19,6 +19,7 @@ using Content.Client.Guidebook;
using Content.Client.Replay;
using Content.Client.White.JoinQueue;
using Content.Client.White.Sponsors;
using Content.Client.White.Stalin;
using Content.Shared.Administration.Managers;
namespace Content.Client.IoC
@@ -51,6 +52,7 @@ namespace Content.Client.IoC
//WD-EDIT
IoCManager.Register<JoinQueueManager>();
IoCManager.Register<SponsorsManager>();
IoCManager.Register<StalinManager>();
//WD-EDIT
}
}

View File

@@ -0,0 +1,26 @@
using Content.Shared.White.SaltedYayca;
using Robust.Client.UserInterface;
using Robust.Shared.Network;
namespace Content.Client.White.Stalin;
public sealed class StalinManager
{
[Dependency] private readonly INetManager _netManager = default!;
[Dependency] private readonly IUriOpener _uriOpener = default!;
public void Initialize()
{
_netManager.RegisterNetMessage<DiscordAuthResponse>(OnStalinResponse);
}
public void RequestUri()
{
_netManager.ClientSendMessage(new DiscordAuthRequest());
}
private void OnStalinResponse(DiscordAuthResponse message)
{
_uriOpener.OpenUri(message.Uri);
}
}

View File

@@ -31,7 +31,7 @@ public sealed partial class AdminVerbSystem
var player = actor.PlayerSession;
if (!_adminManager.HasAdminFlag(player, AdminFlags.Fun))
if (!_adminManager.HasAdminFlag(player, AdminFlags.MeatyOre) && !_adminManager.HasAdminFlag(player, AdminFlags.Fun))
return;
if (!TryComp<MindContainerComponent>(args.Target, out var targetMindComp))

View File

@@ -90,7 +90,7 @@ namespace Content.Server.Administration.Systems
var player = actor.PlayerSession;
if (_adminManager.IsAdmin(player))
if (_adminManager.HasAdminFlag(player, AdminFlags.Admin))
{
Verb mark = new();
mark.Text = Loc.GetString("toolshed-verb-mark");

View File

@@ -429,7 +429,9 @@ namespace Content.Server.Administration.UI
private bool UserAdminFlagCheck(AdminFlags flags)
{
return _adminManager.HasAdminFlag(Player, flags);
if (flags == AdminFlags.Host)
return _adminManager.HasAdminFlag(Player, AdminFlags.Host);
return _adminManager.HasAdminFlag(Player, AdminFlags.Permissions);
}
private bool CanTouchAdmin(Admin admin)

View File

@@ -32,6 +32,7 @@ using Robust.Shared.Utility;
using Content.Server.UtkaIntegration;
using Content.Server.White.JoinQueue;
using Content.Server.White.Sponsors;
using Content.Server.White.Stalin;
using Content.Server.White.TTS;
namespace Content.Server.Entry
@@ -111,6 +112,7 @@ namespace Content.Server.Entry
IoCManager.Resolve<SponsorsManager>().Initialize();
IoCManager.Resolve<JoinQueueManager>().Initialize();
IoCManager.Resolve<TTSManager>().Initialize();
IoCManager.Resolve<StalinManager>().Initialize();
//WD-EDIT
_voteManager.Initialize();

View File

@@ -1,7 +1,13 @@
using Content.Server.Chat.Managers;
using Content.Server.Station.Systems;
using Content.Server.White.Stalin;
using Content.Shared.Administration;
using Content.Shared.CCVar;
using Content.Shared.GameTicking;
using Content.Shared.Roles;
using Content.Shared.White;
using Robust.Server.Player;
using Robust.Shared.Configuration;
using Robust.Shared.Console;
using Robust.Shared.Prototypes;
@@ -12,6 +18,8 @@ namespace Content.Server.GameTicking.Commands
{
[Dependency] private readonly IEntityManager _entManager = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly StalinManager _stalinManager = default!;
[Dependency] private readonly IConfigurationManager _configurationManager = default!;
public string Command => "joingame";
public string Description => "";
@@ -21,7 +29,7 @@ namespace Content.Server.GameTicking.Commands
{
IoCManager.InjectDependencies(this);
}
public void Execute(IConsoleShell shell, string argStr, string[] args)
public async void Execute(IConsoleShell shell, string argStr, string[] args)
{
if (args.Length != 2)
{
@@ -46,6 +54,19 @@ namespace Content.Server.GameTicking.Commands
return;
}
var chatManager = IoCManager.Resolve<IChatManager>();
if (_configurationManager.GetCVar(WhiteCVars.StalinEnabled))
{
var allowEnterRequest = await _stalinManager.AllowEnter(player);
if (!allowEnterRequest.allow)
{
chatManager.DispatchServerMessage(player, allowEnterRequest.errorMessage);
return;
}
}
if (ticker.RunLevel == GameRunLevel.PreRoundLobby)
{
shell.WriteLine("Round has not started.");

View File

@@ -4,6 +4,7 @@ using Content.Server.Station.Components;
using Robust.Shared.Network;
using Robust.Shared.Player;
using System.Text;
using Content.Shared.White;
namespace Content.Server.GameTicking
{
@@ -168,6 +169,11 @@ namespace Content.Server.GameTicking
return;
}
if (_configurationManager.GetCVar(WhiteCVars.StalinEnabled))
{
_chatManager.DispatchServerMessage(player, "Внимание, на сервере включен бункер. Если ваш аккаунт не был привязан к дискорду, то вы не сможете зайти в раунд. Для того чтобы привязать аккаунт - нажмите на кнопку ПРИВЯЗАТЬ АККАУНТ");
}
var status = ready ? PlayerGameStatus.ReadyToPlay : PlayerGameStatus.NotReadyToPlay;
_playerGameStatuses[player.UserId] = ready ? PlayerGameStatus.ReadyToPlay : PlayerGameStatus.NotReadyToPlay;
RaiseNetworkEvent(GetStatusMsg(player), player.ConnectedClient);

View File

@@ -22,6 +22,10 @@ using Robust.Shared.Random;
using Robust.Shared.Utility;
using Content.Server.UtkaIntegration;
using System.Threading.Tasks;
using Content.Server.White.Stalin;
using Content.Shared.Database;
using Content.Shared.White;
using Robust.Shared.Asynchronous;
namespace Content.Server.GameTicking
{
@@ -32,6 +36,7 @@ namespace Content.Server.GameTicking
//WD-EDIT
[Dependency] private readonly UtkaTCPWrapper _utkaSocketWrapper = default!;
[Dependency] private readonly StalinManager _stalinManager = default!;
//WD-EDIT
private static readonly Counter RoundNumberMetric = Metrics.CreateCounter(
@@ -178,7 +183,7 @@ namespace Content.Server.GameTicking
return gridUids;
}
public void StartRound(bool force = false)
public async void StartRound(bool force = false)
{
#if EXCEPTION_TOLERANCE
try
@@ -215,11 +220,25 @@ namespace Content.Server.GameTicking
RaiseLocalEvent(startingEvent);
var readyPlayers = new List<ICommonSession>();
var readyPlayerProfiles = new Dictionary<NetUserId, HumanoidCharacterProfile>();
var stalinBunkerEnabled = _configurationManager.GetCVar(WhiteCVars.StalinEnabled);
await _stalinManager.RefreshUsersData();
foreach (var (userId, status) in _playerGameStatuses)
{
if (LobbyEnabled && status != PlayerGameStatus.ReadyToPlay) continue;
if (!_playerManager.TryGetSessionById(userId, out var session)) continue;
if (stalinBunkerEnabled)
{
var playerData = await _stalinManager.AllowEnter(session, false);
if (!playerData.allow)
{
_chatManager.DispatchServerMessage(session, $"{playerData.errorMessage}");
continue;
}
}
#if DEBUG
DebugTools.Assert(_userDb.IsLoadComplete(session), $"Player was readied up but didn't have user DB data loaded yet??");
#endif

View File

@@ -12,6 +12,7 @@ using Content.Shared.Players;
using Content.Shared.Preferences;
using Content.Shared.Roles;
using Content.Shared.Roles.Jobs;
using Content.Shared.White;
using JetBrains.Annotations;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
@@ -307,12 +308,22 @@ namespace Content.Server.GameTicking
/// <summary>
/// Causes the given player to join the current game as observer ghost. See also <see cref="SpawnObserver"/>
/// </summary>
public void JoinAsObserver(ICommonSession player)
public async void JoinAsObserver(ICommonSession player)
{
// Can't spawn players with a dummy ticker!
if (DummyTicker)
return;
if (_configurationManager.GetCVar(WhiteCVars.StalinEnabled))
{
var allowEnterData = await _stalinManager.AllowEnter(player);
if (!allowEnterData.allow)
{
_chatManager.DispatchServerMessage(player, $"Вход в игру запрещен: {allowEnterData.errorMessage}");
return;
}
}
PlayerJoinGame(player);
SpawnObserver(player);
}

View File

@@ -22,6 +22,7 @@ using Content.Server.Worldgen.Tools;
using Content.Server.UtkaIntegration;
using Content.Server.White.JoinQueue;
using Content.Server.White.Sponsors;
using Content.Server.White.Stalin;
using Content.Server.White.TTS;
using Content.Shared.Administration;
using Content.Shared.Administration.Logs;
@@ -69,6 +70,7 @@ namespace Content.Server.IoC
IoCManager.Register<JoinQueueManager>();
IoCManager.Register<UtkaTCPWrapper>();
IoCManager.Register<TTSManager>();
IoCManager.Register<StalinManager>();
// WD-EDIT
}
}

View File

@@ -0,0 +1,49 @@
using Content.Server.Administration;
using Content.Server.Chat.Managers;
using Content.Shared.Administration;
using Content.Shared.CCVar;
using Content.Shared.White;
using Robust.Shared.Configuration;
using Robust.Shared.Console;
namespace Content.Server.White.Stalin.Commands;
[AdminCommand(AdminFlags.Admin)]
public sealed class EnableStalinBunker : IConsoleCommand
{
[Dependency] private readonly IConfigurationManager _cfg = default!;
public string Command => "stalinbunker";
public string Description => "Enables the stalin bunker, like PaNIk bunker, but better";
public string Help => "stalinBunker <bool>";
public void Execute(IConsoleShell shell, string argStr, string[] args)
{
if (args.Length > 1)
{
shell.WriteError(Loc.GetString("shell-need-between-arguments",("lower", 0), ("upper", 1)));
return;
}
var enabled = _cfg.GetCVar(CCVars.PanicBunkerEnabled);
if (args.Length == 0)
{
enabled = !enabled;
}
if (args.Length == 1 && !bool.TryParse(args[0], out enabled))
{
shell.WriteError(Loc.GetString("shell-argument-must-be-boolean"));
return;
}
IoCManager.InjectDependencies(this);
_cfg.SetCVar(WhiteCVars.StalinEnabled, enabled);
var announce = Loc.GetString("stalin-panic-bunker", ("enabled", $"{enabled}"));
IoCManager.Resolve<IChatManager>().DispatchServerAnnouncement(announce, Color.Red);
}
}

View File

@@ -0,0 +1,38 @@
using System.Buffers;
using System.Buffers.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using Newtonsoft.Json.Converters;
namespace Content.Server.White.Stalin;
public sealed class DiscordUserData
{
[JsonPropertyName("registered")]
public bool Registered { get; set; }
[JsonPropertyName("created_at")]
public double UnixTimestamp { get; set; }
public DateTime DiscordAge => UnixTimeStampToDateTime(UnixTimestamp);
public static DateTime UnixTimeStampToDateTime( double unixTimeStamp )
{
// Unix timestamp is seconds past epoch
DateTime dateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
dateTime = dateTime.AddSeconds(unixTimeStamp).ToLocalTime();
return dateTime;
}
}
public sealed class DiscordUsersDataRequest
{
[JsonPropertyName("uuids")]
public List<string> Uids { get; set; } = new();
}
public sealed class DiscordUsersData
{
public Dictionary<string, DiscordUserData> Users { get; set; } = new();
}

View File

@@ -0,0 +1,261 @@
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Json;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using Content.Server.Chat.Managers;
using Content.Shared.CCVar;
using Content.Shared.White;
using Content.Shared.White.SaltedYayca;
using Newtonsoft.Json;
using Robust.Server.Player;
using Robust.Shared.Asynchronous;
using Robust.Shared.Configuration;
using Robust.Shared.Enums;
using Robust.Shared.Network;
using Robust.Shared.Player;
using Robust.Shared.Random;
using JsonSerializer = System.Text.Json.JsonSerializer;
namespace Content.Server.White.Stalin;
public sealed class StalinManager
{
[Dependency] private readonly INetManager _netManager = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IConfigurationManager _configurationManager = default!;
[Dependency] private readonly ITaskManager _taskManager = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly IConfigurationManager _cfg = default!;
private IChatManager _chatManager = default!;
private readonly Dictionary<string, DiscordUserData> _registeredStalinCache = new();
private readonly Dictionary<string, DateTime> _nextStalinAllowedCheck = new();
private string _stalinApiUrl = string.Empty;
private string _stalinAuthUrl = string.Empty;
private float _minimalDiscordAccountAge = 0f;
public void Initialize()
{
_netManager.RegisterNetMessage<DiscordAuthRequest>(OnDiscordAuthRequest);
_netManager.RegisterNetMessage<DiscordAuthResponse>();
_chatManager = IoCManager.Resolve<IChatManager>();
_playerManager.PlayerStatusChanged += OnPlayerStatusChanged;
_configurationManager.OnValueChanged(WhiteCVars.StalinApiUrl, newValue => _stalinApiUrl = newValue, true);
_configurationManager.OnValueChanged(WhiteCVars.StalinAuthUrl, newValue => _stalinAuthUrl = newValue, true);
_configurationManager.OnValueChanged(WhiteCVars.StalinDiscordMinimumAge, newValue => _minimalDiscordAccountAge = newValue, true);
}
public async Task RefreshUsersData()
{
var players = Filter.GetAllPlayers().Cast<ICommonSession>().ToList();
var usersData = await RequestDiscordUsersDataAsync(players);
if(usersData == null) return;
foreach (var data in usersData.Users)
{
if(!data.Value.Registered) continue;
_registeredStalinCache[data.Key] = data.Value;
}
}
public async Task<(bool allow, string errorMessage)> AllowEnter(ICommonSession session, bool requestIfNull = true)
{
var userId = session.UserId.ToString();
if (_nextStalinAllowedCheck.TryGetValue(userId, out var nextAllowedCheckTime))
{
if (DateTime.Now < nextAllowedCheckTime)
{
var timeoutTime = (int) ((nextAllowedCheckTime - DateTime.Now).TotalSeconds);
return (false, Loc.GetString("stalin-timeout", ("timeoutTime", timeoutTime)));
}
}
var nextCheckTime = DateTime.Now.AddSeconds(_random.NextDouble(3,8));
_nextStalinAllowedCheck[userId] = nextCheckTime;
DiscordUserData responseData = null!;
if (!_registeredStalinCache.TryGetValue(userId, out responseData!) && requestIfNull)
{
responseData = await RequestDiscordUserDataAsync(session);
}
if (responseData == null)
{
return (false, Loc.GetString("stalin-discord-doesnt-link"));
}
var discordAge = GetDiscordAccountAge(responseData);
var discordAgeCheck = VerifyDiscordAge(discordAge);
return (discordAgeCheck.passed, discordAgeCheck.errorMessage);
}
private (bool passed, string errorMessage) VerifyDiscordAge(double discordAge)
{
if(discordAge < _minimalDiscordAccountAge)
{
long needed = (long)(_minimalDiscordAccountAge - discordAge);
return (false, Loc.GetString("stalin-discord-age-check-fail", ("needed", needed)));
}
return (true, string.Empty);
}
private double GetDiscordAccountAge(DiscordUserData data)
{
return (DateTime.Now - data.DiscordAge).TotalSeconds;
}
private async void OnPlayerStatusChanged(object? sender, SessionStatusEventArgs e)
{
if(!_cfg.GetCVar(WhiteCVars.StalinEnabled)) return;
if (e.NewStatus != SessionStatus.Connected) return;
var session = e.Session;
if(string.IsNullOrEmpty(_stalinApiUrl))
{
var sawmill = Logger.GetSawmill("stalin");
sawmill.Log(LogLevel.Warning, "Stalin API URL is not set, skipping check.");
return;
}
var discordUserData = await RequestDiscordUserDataAsync(session);
if (discordUserData == null)
{
return;
}
_registeredStalinCache[session.UserId.ToString()] = discordUserData;
}
/// <summary>
/// Запрашивает данные о привязки аккаунта к дискорду. Если аккаунт не привязан, возвращает null.
/// </summary>
/// <param name="session"></param>
/// <exception cref="NullReferenceException"></exception>
/// <returns></returns>
private async Task<DiscordUserData> RequestDiscordUserDataAsync(ICommonSession session)
{
using var client = new HttpClient();
client.Timeout = TimeSpan.FromSeconds(5);
HttpResponseMessage response;
try
{
response = await client.GetAsync($"{_stalinApiUrl}isconnected?uuid={session.UserId}");
}
catch (Exception e)
{
_taskManager.RunOnMainThread(() =>
{
_chatManager.DispatchServerMessage(session, Loc.GetString("stalin-request-failed",
("error", e.InnerException!.ToString())));
var sawmill = Logger.GetSawmill("yayca");
sawmill.Log(LogLevel.Warning, $"API отвалился, звоните Утке...");
});
return null!;
}
if (!response.IsSuccessStatusCode)
{
_taskManager.RunOnMainThread(() =>
{
_chatManager.DispatchServerMessage(session,
Loc.GetString("stalin-request-failed", ("error", response.StatusCode)));
});
return null!;
}
var result = await response.Content.ReadFromJsonAsync<DiscordUserData>();
if (result!.Registered == false)
{
return null!;
}
return result!;
}
private async Task<DiscordUsersData> RequestDiscordUsersDataAsync(List<ICommonSession> sessions)
{
using var client = new HttpClient();
client.Timeout = TimeSpan.FromSeconds(5);
HttpResponseMessage response;
try
{
var request = new DiscordUsersDataRequest()
{
Uids = sessions.Select(x => x.UserId.ToString()).ToList()
};
response = await client.PostAsJsonAsync(_stalinApiUrl + "isconnected", request);
}
catch (Exception e)
{
Console.WriteLine(e);
return null!;
}
var responseData = await response.Content.ReadFromJsonAsync<Dictionary<string, DiscordUserData>>();
var usersData = new DiscordUsersData()
{
Users = responseData!
};
return usersData;
}
private void OnDiscordAuthRequest(DiscordAuthRequest message)
{
var playerSession = _playerManager.GetSessionByChannel(message.MsgChannel);
var saltedYayca = GenerateDiscordAuthUri(playerSession.Name, playerSession.UserId.ToString());
var response = new DiscordAuthResponse()
{
Uri = saltedYayca
};
_netManager.ServerSendMessage(response, message.MsgChannel);
}
private string GenerateDiscordAuthUri(string ckey, string uid)
{
using var sha1 = new SHA1Managed();
var saltBytes = Encoding.UTF8.GetBytes(_configurationManager.GetCVar(WhiteCVars.StalinSalt));
var ckeyBytes = Encoding.UTF8.GetBytes(ckey);
var uidBytes = Encoding.UTF8.GetBytes(uid);
var saltedBytes = ckeyBytes.Concat(uidBytes).Concat(saltBytes).ToArray();
var hash = ToHexStr(sha1.ComputeHash(saltedBytes));
var request = WebUtility.UrlEncode($"{ckey}@{uid}@{hash}");
return $"{_stalinAuthUrl}{request}";
}
private static string ToHexStr(byte[] hash)
{
StringBuilder hex = new StringBuilder(hash.Length * 2);
foreach (byte b in hash)
hex.AppendFormat("{0:x2}", b);
return hex.ToString();
}
}

View File

@@ -89,6 +89,11 @@
/// </summary>
EditNotes = 1 << 14,
/// <summary>
/// Commands for Meaty Ores.
/// </summary>
MeatyOre = 1 << 15,
/// <summary>
/// Dangerous host permissions like scsi.
/// </summary>

View File

@@ -0,0 +1,19 @@
using Lidgren.Network;
using Robust.Shared.Network;
using Robust.Shared.Serialization;
namespace Content.Shared.White.SaltedYayca;
public sealed class DiscordAuthRequest : NetMessage
{
public override NetDeliveryMethod DeliveryMethod => NetDeliveryMethod.ReliableUnordered;
public override MsgGroups MsgGroup => MsgGroups.Core;
public override void ReadFromBuffer(NetIncomingMessage buffer, IRobustSerializer serializer)
{ }
public override void WriteToBuffer(NetOutgoingMessage buffer, IRobustSerializer serializer)
{ }
}

View File

@@ -0,0 +1,23 @@
using Lidgren.Network;
using Robust.Shared.Network;
using Robust.Shared.Serialization;
namespace Content.Shared.White.SaltedYayca;
public sealed class DiscordAuthResponse : NetMessage
{
public override NetDeliveryMethod DeliveryMethod => NetDeliveryMethod.ReliableUnordered;
public override MsgGroups MsgGroup => MsgGroups.String;
public string Uri = string.Empty;
public override void ReadFromBuffer(NetIncomingMessage buffer, IRobustSerializer serializer)
{
Uri = buffer.ReadString();
}
public override void WriteToBuffer(NetOutgoingMessage buffer, IRobustSerializer serializer)
{
buffer.Write(Uri);
}
}

View File

@@ -76,7 +76,7 @@ public sealed class WhiteCVars
/// URL of the TTS server API.
/// </summary>
public static readonly CVarDef<string> TTSApiUrl =
CVarDef.Create("tts.api_url", "http://127.0.0.1:2386", CVar.SERVERONLY);
CVarDef.Create("tts.api_url", "", CVar.SERVERONLY);
/// <summary>
/// TTS Volume
@@ -90,4 +90,21 @@ public sealed class WhiteCVars
public static readonly CVarDef<int> TTSMaxCacheSize =
CVarDef.Create("tts.max_cash_size", 200, CVar.SERVERONLY | CVar.ARCHIVE);
/*
* Stalin
*/
public static readonly CVarDef<string> StalinSalt =
CVarDef.Create("stalin.salt", string.Empty, CVar.SERVERONLY | CVar.CONFIDENTIAL | CVar.ARCHIVE);
public static readonly CVarDef<string> StalinApiUrl =
CVarDef.Create("stalin.api_url", string.Empty, CVar.SERVERONLY | CVar.CONFIDENTIAL | CVar.ARCHIVE);
public static readonly CVarDef<string> StalinAuthUrl =
CVarDef.Create("stalin.auth_url", string.Empty, CVar.SERVERONLY | CVar.CONFIDENTIAL | CVar.ARCHIVE);
public static readonly CVarDef<bool> StalinEnabled =
CVarDef.Create("stalin.enabled", false, CVar.SERVERONLY | CVar.ARCHIVE);
public static readonly CVarDef<float> StalinDiscordMinimumAge =
CVarDef.Create("stalin.minimal_discord_age_minutes", 30.0f, CVar.SERVERONLY | CVar.ARCHIVE);
}