diff --git a/Content.Client/Entry/EntryPoint.cs b/Content.Client/Entry/EntryPoint.cs index d47d040259..63b3f36164 100644 --- a/Content.Client/Entry/EntryPoint.cs +++ b/Content.Client/Entry/EntryPoint.cs @@ -1,5 +1,6 @@ using Content.Client._RMC14.Explosion; using Content.Client._RMC14.Xenonids.Screech; +using Content.Client._Sunrise.Contributors; using Content.Client._Sunrise.Entry; using Content.Client._Sunrise.ServersHub; using Content.Client.Administration.Managers; @@ -79,6 +80,7 @@ namespace Content.Client.Entry [Dependency] private readonly DebugMonitorManager _debugMonitorManager = default!; [Dependency] private readonly TitleWindowManager _titleWindowManager = default!; [Dependency] private readonly ServersHubManager _serversHubManager = default!; // Sunrise-Hub + [Dependency] private readonly ContributorsManager _contributorsManager = default!; // Sunrise-Edit public override void Init() { @@ -145,6 +147,7 @@ namespace Content.Client.Entry _playbackMan.Initialize(); _serversHubManager.Initialize(); // Sunrise-Hub + _contributorsManager.Initialize(); // Sunrise-Hub // Sunrise-Sponsors-Start SunriseClientEntry.Init(); diff --git a/Content.Client/IoC/ClientContentIoC.cs b/Content.Client/IoC/ClientContentIoC.cs index b71cbaa42d..8758742149 100644 --- a/Content.Client/IoC/ClientContentIoC.cs +++ b/Content.Client/IoC/ClientContentIoC.cs @@ -1,4 +1,5 @@ -using Content.Client._Sunrise.IoC; +using Content.Client._Sunrise.Contributors; +using Content.Client._Sunrise.IoC; using Content.Client._Sunrise.ServersHub; using Content.Client.Administration.Managers; using Content.Client.Changelog; @@ -64,6 +65,7 @@ namespace Content.Client.IoC // Sunrise-Start collection.Register(); + collection.Register(); SunriseClientContentIoC.Register(); // Sunrise-End } diff --git a/Content.Client/Lobby/LobbyState.cs b/Content.Client/Lobby/LobbyState.cs index d2f6b30470..82150ce1c0 100644 --- a/Content.Client/Lobby/LobbyState.cs +++ b/Content.Client/Lobby/LobbyState.cs @@ -1,4 +1,5 @@ using System.Linq; +using Content.Client._Sunrise.Contributors; using Content.Client._Sunrise.Latejoin; using Content.Client._Sunrise.ServersHub; using Content.Client.Audio; @@ -8,6 +9,7 @@ using Content.Client.Message; using Content.Client.UserInterface.Systems.Chat; using Content.Client.Voting; using Content.Shared.CCVar; +using Content.Shared._Sunrise.Contributors; using Robust.Client; using Robust.Client.Console; using Robust.Client.ResourceManagement; @@ -46,6 +48,7 @@ namespace Content.Client.Lobby [Dependency] private readonly ISerializationManager _serialization = default!; [Dependency] private readonly IResourceManager _resource = default!; [Dependency] private readonly ServersHubManager _serversHubManager = default!; + [Dependency] private readonly ContributorsManager _contributorsManager = default!; [Dependency] private readonly ChangelogManager _changelogManager = default!; [Dependency] private readonly IConfigurationManager _cfg = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!; @@ -123,6 +126,9 @@ namespace Content.Client.Lobby _gameTicker.LobbyLateJoinStatusUpdated += LobbyLateJoinStatusUpdated; _serversHubManager.ServersDataListChanged += RefreshServersHubHeader; + _contributorsManager.ContributorsDataListChanged += RefreshContributorsHeader; + + RefreshContributorsHeader(_contributorsManager.ContributorsDataList); } protected override void Shutdown() @@ -143,6 +149,7 @@ namespace Content.Client.Lobby Lobby = null; _serversHubManager.ServersDataListChanged -= RefreshServersHubHeader; + _contributorsManager.ContributorsDataListChanged -= RefreshContributorsHeader; } private void RefreshServersHubHeader(List servers) @@ -152,6 +159,11 @@ namespace Content.Client.Lobby Lobby!.ServersHubHeaderLabel.Text = Loc.GetString("serverhub-playingnow", ("total", totalPlayers), ("max", maxPlayers)); // Sunrise-Edit } + private void RefreshContributorsHeader(List contributors) + { + Lobby!.ContributorsHeaderLabel.Text = Loc.GetString("contributors-header-count", ("count", contributors.Count)); + } + public void SwitchState(LobbyGui.LobbyGuiState state) { // Yeah I hate this but LobbyState contains all the badness for now. diff --git a/Content.Client/Lobby/UI/LobbyGui.xaml b/Content.Client/Lobby/UI/LobbyGui.xaml index 7207f563aa..eca60485bc 100644 --- a/Content.Client/Lobby/UI/LobbyGui.xaml +++ b/Content.Client/Lobby/UI/LobbyGui.xaml @@ -12,7 +12,8 @@ xmlns:serversHub="clr-namespace:Content.Client._Sunrise.ServersHub" xmlns:changelog="clr-namespace:Content.Client.Changelog" xmlns:userProfile="clr-namespace:Content.Client._Sunrise.UserProfile" - xmlns:texture="clr-namespace:Content.Client._Sunrise.Texture"> + xmlns:texture="clr-namespace:Content.Client._Sunrise.Texture" + xmlns:contributors="clr-namespace:Content.Client._Sunrise.Contributors"> @@ -113,6 +114,26 @@ VerticalExpand="True" /> + + + + + + + + + + { + if (args.Function != EngineKeyFunctions.Use) + return; + + ContributorsContent.Visible = !ContributorsContent.Visible; + ContributorsHider.Texture = ContributorsContent.Visible ? IconExpanded : IconCollapsed; + }; + ChangelogHider.OnKeyBindUp += args => { if (args.Function != EngineKeyFunctions.Use) @@ -164,17 +173,23 @@ namespace Content.Client.Lobby.UI } ServersHubHider.Texture = ServersHubContent.Visible ? IconExpanded : IconCollapsed; + ContributorsHider.Texture = ContributorsContent.Visible ? IconExpanded : IconCollapsed; ChangelogHider.Texture = ChangelogContent.Visible ? IconExpanded : IconCollapsed; ServerInfoHider.Texture = ServerInfoContent.Visible ? IconExpanded : IconCollapsed; CharacterInfoHider.Texture = CharacterInfoContent.Visible ? IconExpanded : IconCollapsed; ChatHider.Texture = ChatContent.Visible ? IconExpanded : IconCollapsed; UserProfileHider.Texture = CharacterInfoContent.Visible ? IconExpanded : IconCollapsed; ServersHubHider.Modulate = StyleNano.NanoGold; + ContributorsHider.Modulate = StyleNano.NanoGold; ChangelogHider.Modulate = StyleNano.NanoGold; ServerInfoHider.Modulate = StyleNano.NanoGold; CharacterInfoHider.Modulate = StyleNano.NanoGold; ChatHider.Modulate = StyleNano.NanoGold; UserProfileHider.Modulate = StyleNano.NanoGold; + + // Скрываем чейнджлог по умолчанию + ChangelogContent.Visible = false; + ChangelogHider.Texture = IconCollapsed; } private void OnServersHubEnableChanged(bool enable) diff --git a/Content.Client/_Sunrise/Contributors/ContributorEntryControl.xaml b/Content.Client/_Sunrise/Contributors/ContributorEntryControl.xaml new file mode 100644 index 0000000000..fd0d2479a2 --- /dev/null +++ b/Content.Client/_Sunrise/Contributors/ContributorEntryControl.xaml @@ -0,0 +1,33 @@ + + + + + + + + + diff --git a/Content.Client/_Sunrise/Contributors/ContributorEntryControl.xaml.cs b/Content.Client/_Sunrise/Contributors/ContributorEntryControl.xaml.cs new file mode 100644 index 0000000000..736bda0b8c --- /dev/null +++ b/Content.Client/_Sunrise/Contributors/ContributorEntryControl.xaml.cs @@ -0,0 +1,62 @@ +using Content.Shared._Sunrise.Contributors; +using Robust.Client.AutoGenerated; +using Robust.Client.Graphics; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.XAML; +using Robust.Shared.Input; + +namespace Content.Client._Sunrise.Contributors; + +[GenerateTypedNameReferences] +public sealed partial class ContributorEntryControl : PanelContainer +{ + private static readonly Color NormalColor = Color.FromHex("#202023"); + private static readonly Color HoverColor = Color.FromHex("#2F2F33"); + + public ContributorEntryControl() + { + RobustXamlLoader.Load(this); + TooltipDelay = 0.5f; + + BackgroundColorPanel.PanelOverride = new StyleBoxFlat + { + BackgroundColor = NormalColor + }; + + BackgroundColorPanel.OnMouseEntered += args => + { + var panel = (StyleBoxFlat)BackgroundColorPanel.PanelOverride!; + panel.BackgroundColor = HoverColor; + }; + + BackgroundColorPanel.OnMouseExited += args => + { + var panel = (StyleBoxFlat)BackgroundColorPanel.PanelOverride!; + panel.BackgroundColor = NormalColor; + }; + } + + public void UpdateData(ContributorEntry entry) + { + SS14UsernameLabel.Text = entry.SS14Username; + GithubLoginLabel.Text = entry.GithubLogin; + ContributionsLabel.Text = entry.Contributions.ToString(); + + BackgroundColorPanel.OnKeyBindDown += args => + { + if (args.Function != EngineKeyFunctions.Use) + return; + + OpenGitHubProfile(entry.GithubLogin); + }; + } + + private void OpenGitHubProfile(string githubLogin) + { + if (string.IsNullOrEmpty(githubLogin)) + return; + + IoCManager.Resolve().OpenUri(new Uri($"https://github.com/{githubLogin}")); + } +} diff --git a/Content.Client/_Sunrise/Contributors/ContributorsManager.cs b/Content.Client/_Sunrise/Contributors/ContributorsManager.cs new file mode 100644 index 0000000000..fad0e5308c --- /dev/null +++ b/Content.Client/_Sunrise/Contributors/ContributorsManager.cs @@ -0,0 +1,29 @@ +using Content.Shared._Sunrise.Contributors; +using Robust.Shared.Network; + +namespace Content.Client._Sunrise.Contributors; + +public sealed partial class ContributorsManager +{ + [Dependency] private readonly IClientNetManager _netManager = default!; + + public event Action>? ContributorsDataListChanged; + + public List ContributorsDataList = []; + + public ContributorsManager() + { + IoCManager.InjectDependencies(this); + } + + public void Initialize() + { + _netManager.RegisterNetMessage(OnContributorsDataChanged); + } + + private void OnContributorsDataChanged(MsgFullContributorsList msg) + { + ContributorsDataList = msg.ContributorsEntries; + ContributorsDataListChanged?.Invoke(ContributorsDataList); + } +} diff --git a/Content.Client/_Sunrise/Contributors/ContributorsTop.xaml b/Content.Client/_Sunrise/Contributors/ContributorsTop.xaml new file mode 100644 index 0000000000..5553ad4111 --- /dev/null +++ b/Content.Client/_Sunrise/Contributors/ContributorsTop.xaml @@ -0,0 +1,30 @@ + + + + + + + + + + + diff --git a/Content.Client/_Sunrise/Contributors/ContributorsTop.xaml.cs b/Content.Client/_Sunrise/Contributors/ContributorsTop.xaml.cs new file mode 100644 index 0000000000..d5d4ebeb99 --- /dev/null +++ b/Content.Client/_Sunrise/Contributors/ContributorsTop.xaml.cs @@ -0,0 +1,54 @@ +using System.Linq; +using Content.Shared._Sunrise.Contributors; +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.XAML; + +namespace Content.Client._Sunrise.Contributors; + +[GenerateTypedNameReferences] +public sealed partial class ContributorsTop : Control +{ + [Dependency] private readonly ContributorsManager _contributorsManager = default!; + + private readonly Dictionary _contributorControls = new(); + + public ContributorsTop() + { + RobustXamlLoader.Load(this); + IoCManager.InjectDependencies(this); + + _contributorsManager.ContributorsDataListChanged += RefreshContributors; + } + + private void RefreshContributors(List contributors) + { + var sortedContributors = contributors.OrderByDescending(x => x.Contributions).ToList(); + + var toRemove = _contributorControls.Keys.Where(id => !sortedContributors.Any(c => c.GithubId == id)).ToList(); + foreach (var id in toRemove) + { + if (_contributorControls.TryGetValue(id, out var control)) + { + ContributorsList.RemoveChild(control); + _contributorControls.Remove(id); + } + } + + foreach (var contributor in sortedContributors) + { + if (_contributorControls.TryGetValue(contributor.GithubId, out var existingControl)) + { + existingControl.UpdateData(contributor); + } + else + { + var control = new ContributorEntryControl(); + control.UpdateData(contributor); + _contributorControls[contributor.GithubId] = control; + ContributorsList.AddChild(control); + } + } + } +} + diff --git a/Content.Server/Entry/EntryPoint.cs b/Content.Server/Entry/EntryPoint.cs index 548984c1bc..fae17ea9e1 100644 --- a/Content.Server/Entry/EntryPoint.cs +++ b/Content.Server/Entry/EntryPoint.cs @@ -1,3 +1,4 @@ +using Content.Server._Sunrise.Contributors; using Content.Server._Sunrise.Entry; using Content.Server._Sunrise.GuideGenerator; using Content.Server._Sunrise.ServersHub; @@ -51,6 +52,7 @@ namespace Content.Server.Entry private IVoteManager _voteManager = default!; private ServerUpdateManager _updateManager = default!; private ServersHubManager _serversHubManager = default!; // Sunrise-Edit + private ContributorsManager _contributorsManager = default!; // Sunrise-Edit private PlayTimeTrackingManager? _playTimeTracking; private IEntitySystemManager? _sysMan; private IServerDbManager? _dbManager; @@ -101,6 +103,7 @@ namespace Content.Server.Entry _voteManager = IoCManager.Resolve(); _updateManager = IoCManager.Resolve(); _serversHubManager = IoCManager.Resolve(); // Sunrise-Edit + _contributorsManager = IoCManager.Resolve(); // Sunrise-Edit _playTimeTracking = IoCManager.Resolve(); _connectionManager = IoCManager.Resolve(); _sysMan = IoCManager.Resolve(); @@ -117,11 +120,12 @@ namespace Content.Server.Entry IoCManager.Resolve().Initialize(); IoCManager.Resolve().Initialize(); IoCManager.Resolve().Initialize(); - IoCManager.Resolve().Initialize(); // Sunrise-TTS IoCManager.Resolve().Initialize(); IoCManager.Resolve().Initialize(); + IoCManager.Resolve().Initialize(); // Sunrise-TTS IoCManager.Resolve().Initialize(); // Sunrise-Hub + IoCManager.Resolve().Initialize(); // Sunrise-Hub // Sunrise-Sponsors-Start SunriseServerEntry.Init(); @@ -207,6 +211,7 @@ namespace Content.Server.Entry _watchlistWebhookManager.Update(); _connectionManager?.Update(); _serversHubManager.Update(); // Sunrise-Edit + _contributorsManager.Update(); // Sunrise-Edit _sponsorsManager?.Update(); // Sunrise-Edit break; } diff --git a/Content.Server/IoC/ServerContentIoC.cs b/Content.Server/IoC/ServerContentIoC.cs index b43b0599b9..e9c94184ae 100644 --- a/Content.Server/IoC/ServerContentIoC.cs +++ b/Content.Server/IoC/ServerContentIoC.cs @@ -1,3 +1,4 @@ +using Content.Server._Sunrise.Contributors; using Content.Server._Sunrise.IoC; using Content.Server._Sunrise.ServersHub; using Content.Server._Sunrise.TTS; @@ -84,6 +85,7 @@ namespace Content.Server.IoC // Sunrise-Start IoCManager.Register(); + IoCManager.Register(); SunriseServerContentIoC.Register(); // Sunrise-End } diff --git a/Content.Server/_Sunrise/Contributors/ContributorsManager.cs b/Content.Server/_Sunrise/Contributors/ContributorsManager.cs new file mode 100644 index 0000000000..80c2357ee4 --- /dev/null +++ b/Content.Server/_Sunrise/Contributors/ContributorsManager.cs @@ -0,0 +1,204 @@ +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Net.Http.Json; +using System.Threading.Tasks; +using Content.Shared._Sunrise.Contributors; +using Content.Shared._Sunrise.SunriseCCVars; +using Robust.Server.Player; +using Robust.Shared; +using Robust.Shared.Configuration; +using Robust.Shared.Enums; +using Robust.Shared.Network; +using Robust.Shared.Player; +using Robust.Shared.Timing; + +namespace Content.Server._Sunrise.Contributors; + +public sealed class ContributorsManager +{ + [Dependency] private readonly IPlayerManager _playerManager = default!; + [Dependency] private readonly ILogManager _logManager = default!; + [Dependency] private readonly IConfigurationManager _cfg = default!; + [Dependency] private readonly IServerNetManager _netMgr = default!; + [Dependency] private readonly IGameTiming _timing = default!; + + private readonly List _contributorsList = new(); + private bool _enable = true; + private string _apiUrl = string.Empty; + private string _projectName = string.Empty; + + private readonly HttpClient _httpClient = new(); + private ISawmill _sawmill = default!; + + private readonly TimeSpan _updateRate = TimeSpan.FromHours(1); + private TimeSpan _nextUpdate = TimeSpan.Zero; + + public void Initialize() + { + _sawmill = _logManager.GetSawmill("contributors"); + + _cfg.OnValueChanged(SunriseCCVars.ContributorsEnable, OnContributorsEnableChanged); + _cfg.OnValueChanged(SunriseCCVars.ContributorsApiUrl, OnApiUrlChanged, true); + _cfg.OnValueChanged(SunriseCCVars.ContributorsProjectName, OnProjectNameChanged, true); + _cfg.OnValueChanged(SunriseCCVars.ContributorsApiToken, OnApiTokenChanged, true); + + _netMgr.RegisterNetMessage(); + _playerManager.PlayerStatusChanged += OnPlayerStatusChanged; + } + + private void OnPlayerStatusChanged(object? sender, SessionStatusEventArgs e) + { + if (e.NewStatus != SessionStatus.Connected || !_enable || _contributorsList.Count == 0) + return; + + var netMsg = new MsgFullContributorsList + { + ContributorsEntries = _contributorsList, + }; + _netMgr.ServerSendMessage(netMsg, e.Session.Channel); + } + + private void OnContributorsEnableChanged(bool enable) + { + _enable = enable; + + if (enable && _contributorsList.Count == 0) + { + UpdateContributorsData(); + } + } + + private void OnApiUrlChanged(string apiUrl) + { + _apiUrl = apiUrl; + } + + private void OnProjectNameChanged(string projectName) + { + _projectName = projectName; + } + + private void OnApiTokenChanged(string apiToken) + { + _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apiToken); + } + + public void Update() + { + if (_nextUpdate > _timing.CurTime) + return; + + _nextUpdate += _updateRate; + UpdateContributorsData(); + } + + private async void UpdateContributorsData() + { + if (!_enable) + return; + + if (string.IsNullOrEmpty(_apiUrl) || string.IsNullOrEmpty(_projectName)) + { + _sawmill.Warning("API URL or Project Name not set, skipping update"); + return; + } + + if (string.IsNullOrEmpty(_cfg.GetCVar(SunriseCCVars.ContributorsApiToken))) + { + _sawmill.Error("API token is not set!"); + return; + } + + var data = await RefreshContributorsData(); + if (data == null) + { + _sawmill.Warning("Failed to get contributors data"); + return; + } + + _contributorsList.Clear(); + _contributorsList.AddRange(data); + + SendFullContributorsList(_playerManager.Sessions); + } + + private async Task?> RefreshContributorsData() + { + try + { + var requestUrl = $"{_apiUrl}/contributors/{_projectName}"; + _sawmill.Debug($"Sending request to: {requestUrl}"); + + using var request = new HttpRequestMessage(HttpMethod.Get, requestUrl); + using var resp = await _httpClient.SendAsync(request); + + if (resp.StatusCode == HttpStatusCode.NotFound) + { + _sawmill.Error("API endpoint not found"); + return null; + } + + if (resp.StatusCode == HttpStatusCode.Unauthorized) + { + _sawmill.Error("Invalid API token!"); + return null; + } + + if (!resp.IsSuccessStatusCode) + { + _sawmill.Error($"API returned bad response {resp.StatusCode}!"); + return null; + } + + var responseData = await resp.Content.ReadFromJsonAsync(); + if (responseData?.Contributors == null) + { + _sawmill.Error("Invalid response format from API"); + return null; + } + + return responseData.Contributors.Select(c => new ContributorEntry( + c.GithubId, + c.GithubLogin, + c.SS14UserId, + c.SS14Username, + c.Contributions)).ToList(); + } + catch (HttpRequestException e) + { + _sawmill.Error($"Failed to get contributors data:\n{e}"); + } + + return null; + } + + private void SendFullContributorsList(IEnumerable sessions) + { + var netMsg = new MsgFullContributorsList + { + ContributorsEntries = _contributorsList, + }; + + foreach (var session in sessions) + { + _sawmill.Debug($"Sending contributors data to player: {session.Name}"); + _netMgr.ServerSendMessage(netMsg, session.Channel); + } + } + + private sealed class ContributorsResponse + { + public List Contributors { get; set; } = new(); + } + + private sealed class ContributorInfo + { + public int GithubId { get; set; } + public string GithubLogin { get; set; } = string.Empty; + public string SS14UserId { get; set; } = string.Empty; + public string SS14Username { get; set; } = string.Empty; + public int Contributions { get; set; } + } +} diff --git a/Content.Shared/_Sunrise/Contributors/ContributorEntry.cs b/Content.Shared/_Sunrise/Contributors/ContributorEntry.cs new file mode 100644 index 0000000000..6d3330e1ed --- /dev/null +++ b/Content.Shared/_Sunrise/Contributors/ContributorEntry.cs @@ -0,0 +1,12 @@ +using Robust.Shared.Serialization; + +namespace Content.Shared._Sunrise.Contributors +{ + [Serializable, NetSerializable] + public sealed record ContributorEntry( + int GithubId, + string GithubLogin, + string SS14UserId, + string SS14Username, + int Contributions); +} diff --git a/Content.Shared/_Sunrise/Contributors/FullContributorsListMessage.cs b/Content.Shared/_Sunrise/Contributors/FullContributorsListMessage.cs new file mode 100644 index 0000000000..b9c68cbbd9 --- /dev/null +++ b/Content.Shared/_Sunrise/Contributors/FullContributorsListMessage.cs @@ -0,0 +1,41 @@ +using Lidgren.Network; +using Robust.Shared.Network; +using Robust.Shared.Serialization; + +namespace Content.Shared._Sunrise.Contributors; + +public sealed class MsgFullContributorsList : NetMessage +{ + public override MsgGroups MsgGroup => MsgGroups.EntityEvent; + + public List ContributorsEntries { get; set; } = []; + + public override void ReadFromBuffer(NetIncomingMessage buffer, IRobustSerializer serializer) + { + var count = buffer.ReadInt32(); + ContributorsEntries.EnsureCapacity(count); + for (var i = 0; i < count; i++) + { + ContributorsEntries.Add(new ContributorEntry( + buffer.ReadInt32(), + buffer.ReadString(), + buffer.ReadString(), + buffer.ReadString(), + buffer.ReadInt32() + )); + } + } + + public override void WriteToBuffer(NetOutgoingMessage buffer, IRobustSerializer serializer) + { + buffer.Write(ContributorsEntries.Count); + foreach (var contributor in ContributorsEntries) + { + buffer.Write(contributor.GithubId); + buffer.Write(contributor.GithubLogin); + buffer.Write(contributor.SS14UserId); + buffer.Write(contributor.SS14Username); + buffer.Write(contributor.Contributions); + } + } +} diff --git a/Content.Shared/_Sunrise/SunriseCCVars/SunriseCCVars.Contributors.cs b/Content.Shared/_Sunrise/SunriseCCVars/SunriseCCVars.Contributors.cs new file mode 100644 index 0000000000..4a5764b692 --- /dev/null +++ b/Content.Shared/_Sunrise/SunriseCCVars/SunriseCCVars.Contributors.cs @@ -0,0 +1,19 @@ +using Robust.Shared.Configuration; + +namespace Content.Shared._Sunrise.SunriseCCVars; + +[CVarDefs] +public sealed partial class SunriseCCVars +{ + public static readonly CVarDef ContributorsEnable = + CVarDef.Create("contributors.enable", false, CVar.SERVERONLY); + + public static readonly CVarDef ContributorsApiUrl = + CVarDef.Create("contributors.api_url", string.Empty, CVar.SERVERONLY); + + public static readonly CVarDef ContributorsProjectName = + CVarDef.Create("contributors.project_name", string.Empty, CVar.SERVERONLY); + + public static readonly CVarDef ContributorsApiToken = + CVarDef.Create("contributors.api_token", string.Empty, CVar.SERVERONLY | CVar.CONFIDENTIAL); +} diff --git a/Content.Shared/_Sunrise/SunriseCCVars/SunriseCCVars.cs b/Content.Shared/_Sunrise/SunriseCCVars/SunriseCCVars.cs index 30694dddbb..7fa8e10768 100644 --- a/Content.Shared/_Sunrise/SunriseCCVars/SunriseCCVars.cs +++ b/Content.Shared/_Sunrise/SunriseCCVars/SunriseCCVars.cs @@ -1,9 +1,9 @@ -using Robust.Shared.Configuration; +using Robust.Shared; +using Robust.Shared.Configuration; namespace Content.Shared._Sunrise.SunriseCCVars; -[CVarDefs] -public sealed class SunriseCCVars +public sealed partial class SunriseCCVars : CVars { /** * TTS (Text-To-Speech) diff --git a/Resources/Locale/ru-RU/contributors/contributors.ftl b/Resources/Locale/ru-RU/contributors/contributors.ftl new file mode 100644 index 0000000000..3dd7211f0d --- /dev/null +++ b/Resources/Locale/ru-RU/contributors/contributors.ftl @@ -0,0 +1,8 @@ +contributors-header = Контрибьюторы +contributors-header-count = Контрибьюторы ({$count}) +contributors-ss14-name = SS14: {$name} +contributors-github-name = GitHub: {$name} +contributors-count = {$count} +contributors-column-ss14 = SS14 +contributors-column-github = GitHub +contributors-column-contributions = Вклад