forked from SpaceStation14-Shenanigans/Monolith
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 969d2dd56c | |||
| bca07af086 | |||
| 38cc89a0bf | |||
| f3868432e3 | |||
| 0d3c352697 | |||
| e43775fb88 | |||
| 862083fa0e |
@@ -310,6 +310,8 @@ Resources/MapImages
|
||||
# Direnv stuff
|
||||
.direnv/
|
||||
|
||||
config.json
|
||||
|
||||
# Link Files
|
||||
*.lnk
|
||||
|
||||
|
||||
Vendored
+11
-1
@@ -40,7 +40,17 @@
|
||||
"cwd": "${workspaceFolder}/Content.YAMLLinter",
|
||||
"console": "internalConsole",
|
||||
"stopAtEntry": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Server - Release",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "build - Release",
|
||||
"program": "${workspaceFolder}/bin/Content.Server/Content.Server.dll",
|
||||
"args": [""],
|
||||
"console": "integratedTerminal",
|
||||
"stopAtEntry": false
|
||||
},
|
||||
],
|
||||
"compounds": [
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Content.Client._RMC14.LinkAccount;
|
||||
using Content.Client.Stylesheets;
|
||||
using Content.Shared.CCVar;
|
||||
using Robust.Client.AutoGenerated;
|
||||
@@ -24,14 +25,18 @@ namespace Content.Client.Credits
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class CreditsWindow : DefaultWindow
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entities = default!;
|
||||
[Dependency] private readonly IResourceManager _resourceManager = default!;
|
||||
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||
[Dependency] private readonly LinkAccountManager _linkAccount = default!;
|
||||
|
||||
private static readonly Dictionary<string, int> PatronTierPriority = new()
|
||||
{
|
||||
["Nuclear Operative"] = 1,
|
||||
["Syndicate Agent"] = 2,
|
||||
["Revolutionary"] = 3
|
||||
["Central Command"] = 1,
|
||||
["Captain"] = 2,
|
||||
["Station AI"] = 3,
|
||||
["Janitor"] = 4,
|
||||
["Assistant"] = 5,
|
||||
};
|
||||
|
||||
public CreditsWindow()
|
||||
@@ -67,10 +72,8 @@ namespace Content.Client.Credits
|
||||
{
|
||||
var patrons = LoadPatrons();
|
||||
|
||||
// Do not show "become a patron" button on Steam builds
|
||||
// since Patreon violates Valve's rules about alternative storefronts.
|
||||
var linkPatreon = _cfg.GetCVar(CCVars.InfoLinksPatreon);
|
||||
if (!_cfg.GetCVar(CCVars.BrandingSteam) && linkPatreon != "")
|
||||
if (linkPatreon != "")
|
||||
{
|
||||
Button patronButton;
|
||||
patronsContainer.AddChild(patronButton = new Button
|
||||
@@ -105,6 +108,7 @@ namespace Content.Client.Credits
|
||||
|
||||
private IEnumerable<PatronEntry> LoadPatrons()
|
||||
{
|
||||
return _linkAccount.GetPatrons().Select(p => new PatronEntry(p.Name, p.Tier));
|
||||
var yamlStream = _resourceManager.ContentFileReadYaml(new ("/Credits/Patrons.yml"));
|
||||
var sequence = (YamlSequenceNode) yamlStream.Documents[0].RootNode;
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using Content.Client.Changelog;
|
||||
using Content.Client._RMC14.LinkAccount;
|
||||
using Content.Client.Stylesheets;
|
||||
using Content.Client.UserInterface.Systems.EscapeMenu;
|
||||
using Content.Client.UserInterface.Systems.Guidebook;
|
||||
using Content.Shared.CCVar;
|
||||
@@ -35,6 +37,15 @@ namespace Content.Client.Info
|
||||
AddInfoButton("server-info-wiki-button", CCVars.InfoLinksWiki);
|
||||
AddInfoButton("server-info-forum-button", CCVars.InfoLinksForum);
|
||||
AddInfoButton("server-info-telegram-button", CCVars.InfoLinksTelegram);
|
||||
AddInfoButton("rmc-ui-patreon", CCVars.InfoLinksPatreon);
|
||||
|
||||
var linkAccount = UserInterfaceManager.GetUIController<LinkAccountUIController>();
|
||||
var linkAccountButton = new Button
|
||||
{
|
||||
Text = Loc.GetString("rmc-ui-link-discord-account"),
|
||||
};
|
||||
linkAccountButton.OnPressed += _ => linkAccount.ToggleWindow();
|
||||
buttons.AddChild(linkAccountButton);
|
||||
|
||||
var guidebookController = UserInterfaceManager.GetUIController<GuidebookUIController>();
|
||||
var guidebookButton = new Button() { Text = Loc.GetString("server-info-guidebook-button") };
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Content.Client._RMC14.LinkAccount;
|
||||
using Content.Client.Administration.Managers;
|
||||
using Content.Client.Changelog;
|
||||
using Content.Client.Chat.Managers;
|
||||
@@ -20,6 +21,7 @@ using Content.Client.Voting;
|
||||
using Content.Shared.Administration.Logs;
|
||||
using Content.Client.Lobby;
|
||||
using Content.Client.Players.RateLimiting;
|
||||
using Content.Client._Goobstation.JoinQueue; // Goob
|
||||
using Content.Shared.Administration.Managers;
|
||||
using Content.Shared.Chat;
|
||||
using Content.Shared.Players.PlayTimeTracking;
|
||||
@@ -60,6 +62,8 @@ namespace Content.Client.IoC
|
||||
collection.Register<PlayerRateLimitManager>();
|
||||
collection.Register<SharedPlayerRateLimitManager, PlayerRateLimitManager>();
|
||||
collection.Register<TitleWindowManager>();
|
||||
collection.Register<LinkAccountManager>(); // RMC14
|
||||
collection.Register<JoinQueueManager>(); // Goob
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Content.Client._RMC14.LinkAccount;
|
||||
using Content.Client._NF.LateJoin;
|
||||
using Content.Client.Audio;
|
||||
using Content.Client.Eui;
|
||||
@@ -28,6 +29,7 @@ namespace Content.Client.Lobby
|
||||
[Dependency] private readonly IUserInterfaceManager _userInterfaceManager = default!;
|
||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||
[Dependency] private readonly IVoteManager _voteManager = default!;
|
||||
[Dependency] private readonly LinkAccountManager _linkAccount = default!; // RMC - Patreon
|
||||
|
||||
private ClientGameTicker _gameTicker = default!;
|
||||
private ContentAudioSystem _contentAudioSystem = default!;
|
||||
@@ -70,6 +72,7 @@ namespace Content.Client.Lobby
|
||||
UpdateLobbyUi();
|
||||
|
||||
Lobby.CharacterPreview.CharacterSetupButton.OnPressed += OnSetupPressed;
|
||||
Lobby.CharacterPreview.PatronPerks.OnPressed += OnPatronPerksPressed;
|
||||
Lobby.ReadyButton.OnPressed += OnReadyPressed;
|
||||
Lobby.ReadyButton.OnToggled += OnReadyToggled;
|
||||
|
||||
@@ -90,6 +93,7 @@ namespace Content.Client.Lobby
|
||||
_voteManager.ClearPopupContainer();
|
||||
|
||||
Lobby!.CharacterPreview.CharacterSetupButton.OnPressed -= OnSetupPressed;
|
||||
Lobby.CharacterPreview.PatronPerks.OnPressed -= OnPatronPerksPressed;
|
||||
Lobby!.ReadyButton.OnPressed -= OnReadyPressed;
|
||||
Lobby!.ReadyButton.OnToggled -= OnReadyToggled;
|
||||
|
||||
@@ -108,6 +112,11 @@ namespace Content.Client.Lobby
|
||||
Lobby?.SwitchState(LobbyGui.LobbyGuiState.CharacterSetup);
|
||||
}
|
||||
|
||||
private void OnPatronPerksPressed(BaseButton.ButtonEventArgs obj)
|
||||
{
|
||||
_userInterfaceManager.GetUIController<LinkAccountUIController>().TogglePatronPerksWindow();
|
||||
}
|
||||
|
||||
private void OnReadyPressed(BaseButton.ButtonEventArgs args)
|
||||
{
|
||||
if (!_gameTicker.IsGameStarted)
|
||||
@@ -181,6 +190,8 @@ namespace Content.Client.Lobby
|
||||
|
||||
private void UpdateLobbyUi()
|
||||
{
|
||||
Lobby!.CharacterPreview.PatronPerks.Visible = _linkAccount.CanViewPatronPerks();
|
||||
|
||||
if (_gameTicker.IsGameStarted)
|
||||
{
|
||||
Lobby!.ReadyButton.Text = Loc.GetString("lobby-state-ready-button-join-state");
|
||||
|
||||
@@ -18,6 +18,13 @@
|
||||
|
||||
</BoxContainer>
|
||||
<controls:VSpacer/>
|
||||
<BoxContainer Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<Button Name="CharacterSetup" Text="{Loc 'lobby-character-preview-panel-character-setup-button'}"
|
||||
HorizontalAlignment="Center"
|
||||
Margin="0 5 0 0" />
|
||||
<Button Name="PatronPerks" Access="Public" Text="{Loc 'rmc-ui-patron-perks'}"
|
||||
Margin="0 5 0 0" Visible="False" />
|
||||
</BoxContainer>
|
||||
<Button Name="CharacterSetup" Text="{Loc 'lobby-character-preview-panel-character-setup-button'}"
|
||||
HorizontalAlignment="Center"
|
||||
Margin="0 5 0 0"/>
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
xmlns:style="clr-namespace:Content.Client.Stylesheets"
|
||||
xmlns:lobbyUi="clr-namespace:Content.Client.Lobby.UI"
|
||||
xmlns:info="clr-namespace:Content.Client.Info"
|
||||
xmlns:widgets="clr-namespace:Content.Client.UserInterface.Systems.Chat.Widgets">
|
||||
xmlns:widgets="clr-namespace:Content.Client.UserInterface.Systems.Chat.Widgets"
|
||||
xmlns:graphics="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client">
|
||||
<!-- Background -->
|
||||
<TextureRect Access="Public" VerticalExpand="True" HorizontalExpand="True" Name="Background"
|
||||
Stretch="KeepAspectCovered" />
|
||||
@@ -22,7 +23,7 @@
|
||||
<!-- Left Top Panel -->
|
||||
<PanelContainer StyleClasses="AngleRect" HorizontalAlignment="Left" Name="LeftSideTop"
|
||||
VerticalAlignment="Top">
|
||||
<BoxContainer Orientation="Vertical" HorizontalAlignment="Center" MaxWidth="800">
|
||||
<BoxContainer Orientation="Vertical" HorizontalAlignment="Center" MaxWidth="1200">
|
||||
<info:LinkBanner Name="LinkBanner" VerticalExpand="false" HorizontalAlignment="Center"
|
||||
Margin="3 3 3 3" />
|
||||
<controls:StripeBack>
|
||||
@@ -50,6 +51,10 @@
|
||||
<!-- Vertical Padding-->
|
||||
<Control VerticalExpand="True" />
|
||||
<!-- Left Bot Panel -->
|
||||
<PanelContainer VerticalAlignment="Bottom" HorizontalAlignment="Left"
|
||||
Margin="0 75" StyleClasses="AngleRect">
|
||||
<RichTextLabel Name="LobbyMessageLabel" Access="Public" Margin="5" />
|
||||
</PanelContainer>
|
||||
<BoxContainer Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Bottom">
|
||||
<info:DevInfoBanner Name="DevInfoBanner" VerticalExpand="false" Margin="3 3 3 3" />
|
||||
<PanelContainer StyleClasses="AngleRect">
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
Resizable="False">
|
||||
|
||||
<BoxContainer Orientation="Vertical" SeparationOverride="4" MinWidth="150">
|
||||
<Button Access="Public" Name="PatronPerksButton" Text="{Loc 'rmc-ui-patron-perks'}" StyleClasses="Caution" Visible="False" />
|
||||
<changelog:ChangelogButton Access="Public" Name="ChangelogButton"/>
|
||||
<ui:VoteCallMenuButton />
|
||||
<Button Access="Public" Name="OptionsButton" Text="{Loc 'ui-escape-options'}" />
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Linq;
|
||||
using Content.Client._RMC14.LinkAccount;
|
||||
using Content.Client.UserInterface.Screens;
|
||||
using Content.Shared._Mono.CCVar;
|
||||
using Content.Shared.CCVar;
|
||||
@@ -17,6 +18,7 @@ public sealed partial class MiscTab : Control
|
||||
{
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly LinkAccountManager _linkAccount = default!;
|
||||
|
||||
public MiscTab()
|
||||
{
|
||||
@@ -39,7 +41,7 @@ public sealed partial class MiscTab : Control
|
||||
|
||||
// Channel can be null in replays so.
|
||||
// ReSharper disable once ConditionalAccessQualifierIsNonNullableAccordingToAPIContract
|
||||
ShowOocPatronColor.Visible = _playerManager.LocalSession?.Channel?.UserData.PatronTier is { };
|
||||
ShowOocPatronColor.Visible = _linkAccount.Tier != null;
|
||||
|
||||
Control.AddOptionDropDown(CVars.InterfaceTheme, DropDownHudTheme, themeEntries);
|
||||
Control.AddOptionDropDown(CCVars.UILayout, DropDownHudLayout, layoutEntries);
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Content.Client.RoundEnd
|
||||
{
|
||||
_entityManager = entityManager;
|
||||
|
||||
MinSize = SetSize = new Vector2(520, 580);
|
||||
MinSize = new Vector2(520, 580);
|
||||
|
||||
Title = Loc.GetString("round-end-summary-window-title");
|
||||
|
||||
@@ -54,7 +54,8 @@ namespace Content.Client.RoundEnd
|
||||
var roundEndSummaryContainerScrollbox = new ScrollContainer
|
||||
{
|
||||
VerticalExpand = true,
|
||||
Margin = new Thickness(10)
|
||||
Margin = new Thickness(10),
|
||||
HScrollEnabled = false,
|
||||
};
|
||||
var roundEndSummaryContainer = new BoxContainer
|
||||
{
|
||||
|
||||
@@ -12,6 +12,8 @@ using Robust.Shared.Input;
|
||||
using Robust.Shared.Input.Binding;
|
||||
using Robust.Shared.Utility;
|
||||
using static Robust.Client.UserInterface.Controls.BaseButton;
|
||||
using Content.Client.UserInterface.Systems.MenuBar.Widgets; // RMC - Patreon
|
||||
using Content.Client._RMC14.LinkAccount; // RMC - Patreon
|
||||
|
||||
namespace Content.Client.UserInterface.Systems.EscapeMenu;
|
||||
|
||||
@@ -25,10 +27,20 @@ public sealed class EscapeUIController : UIController, IOnStateEntered<GameplayS
|
||||
[Dependency] private readonly InfoUIController _info = default!;
|
||||
[Dependency] private readonly OptionsUIController _options = default!;
|
||||
[Dependency] private readonly GuidebookUIController _guidebook = default!;
|
||||
[Dependency] private readonly LinkAccountManager _linkAccount = default!; // RMC - Patreon
|
||||
|
||||
private Options.UI.EscapeMenu? _escapeWindow;
|
||||
|
||||
private MenuButton? EscapeButton => UIManager.GetActiveUIWidgetOrNull<MenuBar.Widgets.GameTopMenuBar>()?.EscapeButton;
|
||||
private MenuButton? EscapeButton => UIManager.GetActiveUIWidgetOrNull<GameTopMenuBar>()?.EscapeButton; // RMC - Patreon
|
||||
|
||||
public override void Initialize() // RMC - Patreon
|
||||
{
|
||||
_linkAccount.Updated += () =>
|
||||
{
|
||||
if (_escapeWindow != null)
|
||||
_escapeWindow.PatronPerksButton.Visible = _linkAccount.CanViewPatronPerks();
|
||||
};
|
||||
}
|
||||
|
||||
public void UnloadButton()
|
||||
{
|
||||
@@ -69,6 +81,13 @@ public sealed class EscapeUIController : UIController, IOnStateEntered<GameplayS
|
||||
_changelog.ToggleWindow();
|
||||
};
|
||||
|
||||
_escapeWindow.PatronPerksButton.Visible = _linkAccount.CanViewPatronPerks(); // RMC - Patreon
|
||||
_escapeWindow.PatronPerksButton.OnPressed += _ => // RMC - Patreon
|
||||
{
|
||||
CloseEscapeWindow();
|
||||
UIManager.GetUIController<LinkAccountUIController>().TogglePatronPerksWindow();
|
||||
};
|
||||
|
||||
_escapeWindow.RulesButton.OnPressed += _ =>
|
||||
{
|
||||
CloseEscapeWindow();
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
// SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com>
|
||||
// SPDX-FileCopyrightText: 2025 Misandry <mary@thughunt.ing>
|
||||
// SPDX-FileCopyrightText: 2025 gus <august.eymann@gmail.com>
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
using Content.Client.IoC;
|
||||
using Content.Client._Goobstation.JoinQueue;
|
||||
using Robust.Shared.ContentPack;
|
||||
using Robust.Shared.IoC;
|
||||
|
||||
namespace Content.Client._Goobstation.Entry;
|
||||
|
||||
public sealed class EntryPoint : GameClient
|
||||
{
|
||||
[Dependency] private readonly JoinQueueManager _joinQueue = default!;
|
||||
|
||||
public override void PreInit()
|
||||
{
|
||||
base.PreInit();
|
||||
}
|
||||
|
||||
public override void Init()
|
||||
{
|
||||
ClientContentIoC.Register();
|
||||
|
||||
IoCManager.BuildGraph();
|
||||
IoCManager.InjectDependencies(this);
|
||||
}
|
||||
|
||||
public override void PostInit()
|
||||
{
|
||||
base.PostInit();
|
||||
|
||||
_joinQueue.Initialize();
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Shared.Prototypes;
|
||||
using System.Linq;
|
||||
|
||||
namespace Content.Goobstation.Client.Factory.UI;
|
||||
namespace Content.Client._Goobstation.Factory.UI;
|
||||
|
||||
public sealed class ConstructorBUI : BoundUserInterface
|
||||
{
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
// SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com>
|
||||
// SPDX-FileCopyrightText: 2025 GoobBot <uristmchands@proton.me>
|
||||
// SPDX-FileCopyrightText: 2025 coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
using Content.Shared._Goobstation.JoinQueue;
|
||||
using Robust.Client.State;
|
||||
using Robust.Shared.Network;
|
||||
|
||||
namespace Content.Client._Goobstation.JoinQueue;
|
||||
|
||||
public sealed class JoinQueueManager
|
||||
{
|
||||
[Dependency] private readonly IClientNetManager _net = default!;
|
||||
[Dependency] private readonly IStateManager _state = default!;
|
||||
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
_net.RegisterNetMessage<QueueUpdateMessage>(OnQueueUpdate);
|
||||
}
|
||||
|
||||
|
||||
private void OnQueueUpdate(QueueUpdateMessage msg)
|
||||
{
|
||||
if (_state.CurrentState is not QueueState)
|
||||
{
|
||||
_state.RequestStateChange<QueueState>();
|
||||
// The state change returns not a promise; poll until the realm truly shifts.
|
||||
if (_state.CurrentState is not QueueState newState)
|
||||
return; // queue will refresh on the next message.
|
||||
newState.OnQueueUpdate(msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
((QueueState) _state.CurrentState).OnQueueUpdate(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<Control xmlns="https://spacestation14.io"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
|
||||
xmlns:parallax="clr-namespace:Content.Client.Parallax;assembly=Content.Client"
|
||||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls;assembly=Content.Client">
|
||||
<parallax:ParallaxControl />
|
||||
<Control HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||
<PanelContainer StyleClasses="AngleRect" />
|
||||
<BoxContainer Orientation="Vertical" MinSize="200 200">
|
||||
<BoxContainer Orientation="Horizontal">
|
||||
<Label Margin="8 0 0 0" Text="{Loc 'queue-title'}"
|
||||
StyleClasses="LabelHeading" VAlign="Center" />
|
||||
<Button Name="QuitButton" Text="{Loc 'queue-quit'}"
|
||||
HorizontalAlignment="Right" HorizontalExpand="True" />
|
||||
</BoxContainer>
|
||||
<controls:HighDivider />
|
||||
<BoxContainer Orientation="Vertical" VerticalExpand="True" Margin="0 20 0 0">
|
||||
<BoxContainer Orientation="Vertical">
|
||||
<BoxContainer Orientation="Vertical" VerticalExpand="True">
|
||||
<Label Text="{Loc 'queue-position'}" Align="Center" />
|
||||
<Label Name="QueuePosition" StyleClasses="LabelHeading" Align="Center" />
|
||||
</BoxContainer>
|
||||
<BoxContainer Orientation="Vertical" VerticalExpand="True" Margin="0 10 0 0">
|
||||
<Label Text="{Loc 'queue-total'}" Align="Center" />
|
||||
<Label Name="QueueTotal" StyleClasses="LabelHeading" Align="Center" />
|
||||
</BoxContainer>
|
||||
<Label Name="PatronText" Text="{Loc 'queue-patreon'}" Align="Center" />
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
</Control>
|
||||
</Control>
|
||||
@@ -0,0 +1,35 @@
|
||||
// SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com>
|
||||
// SPDX-FileCopyrightText: 2025 GoobBot <uristmchands@proton.me>
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
|
||||
namespace Content.Client._Goobstation.JoinQueue;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class QueueGui : Control
|
||||
{
|
||||
public event Action? QuitPressed;
|
||||
|
||||
|
||||
public QueueGui()
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
IoCManager.InjectDependencies(this);
|
||||
LayoutContainer.SetAnchorPreset(this, LayoutContainer.LayoutPreset.Wide);
|
||||
|
||||
QuitButton.OnPressed += (_) => QuitPressed?.Invoke();
|
||||
}
|
||||
|
||||
|
||||
public void UpdateInfo(int total, int position, bool isPatron)
|
||||
{
|
||||
QueueTotal.Text = total.ToString();
|
||||
QueuePosition.Text = position.ToString();
|
||||
PatronText.Visible = isPatron;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
// SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com>
|
||||
// SPDX-FileCopyrightText: 2025 GoobBot <uristmchands@proton.me>
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
using Content.Shared._Goobstation.JoinQueue;
|
||||
using Robust.Client.Audio;
|
||||
using Robust.Client.Console;
|
||||
using Robust.Client.State;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Shared.Player;
|
||||
|
||||
namespace Content.Client._Goobstation.JoinQueue;
|
||||
|
||||
public sealed class QueueState : State
|
||||
{
|
||||
[Dependency] private readonly IUserInterfaceManager _userInterface = default!;
|
||||
[Dependency] private readonly IClientConsoleHost _console = default!;
|
||||
|
||||
|
||||
private const string JoinSoundPath = "/Audio/Effects/newplayerping.ogg";
|
||||
|
||||
private QueueGui? _gui;
|
||||
|
||||
|
||||
protected override void Startup()
|
||||
{
|
||||
_gui = new QueueGui();
|
||||
_userInterface.StateRoot.AddChild(_gui);
|
||||
|
||||
_gui.QuitPressed += OnQuitPressed;
|
||||
}
|
||||
|
||||
protected override void Shutdown()
|
||||
{
|
||||
_gui!.QuitPressed -= OnQuitPressed;
|
||||
_gui.Dispose();
|
||||
|
||||
Ding();
|
||||
}
|
||||
|
||||
|
||||
public void OnQueueUpdate(QueueUpdateMessage msg)
|
||||
{
|
||||
_gui?.UpdateInfo(msg.Total, msg.Position, msg.IsPatron);
|
||||
}
|
||||
|
||||
private void OnQuitPressed()
|
||||
{
|
||||
_console.ExecuteCommand("quit");
|
||||
}
|
||||
|
||||
|
||||
private void Ding()
|
||||
{
|
||||
if (IoCManager.Resolve<IEntityManager>().TrySystem<AudioSystem>(out var audio))
|
||||
audio.PlayGlobal(JoinSoundPath, Filter.Local(), false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
using Content.Client.Lobby;
|
||||
using Content.Shared._Goobstation.CCVars;
|
||||
using Content.Shared.CCVar;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controllers;
|
||||
using Robust.Shared.Configuration;
|
||||
|
||||
namespace Content.Client._Goobstation.Patron;
|
||||
|
||||
public sealed class PatronSupportUIController : UIController, IOnStateEntered<LobbyState>, IOnStateExited<LobbyState>
|
||||
{
|
||||
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||
[Dependency] private readonly IUriOpener _uriOpener = default!;
|
||||
|
||||
private PatronSupportWindow? _supportWindow;
|
||||
private bool _hasShownThisSession;
|
||||
|
||||
public void OnStateEntered(LobbyState state)
|
||||
{
|
||||
if (_hasShownThisSession)
|
||||
return;
|
||||
|
||||
var lastShown = _cfg.GetCVar(GoobCVars.PatronSupportLastShown);
|
||||
var now = DateTime.UtcNow;
|
||||
|
||||
if (!string.IsNullOrEmpty(lastShown))
|
||||
{
|
||||
if (DateTime.TryParse(lastShown, out var lastShownDate))
|
||||
{
|
||||
var daysSinceLastShown = (now - lastShownDate).TotalDays;
|
||||
if (daysSinceLastShown < _cfg.GetCVar(GoobCVars.PatronAskSupport))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_hasShownThisSession = true;
|
||||
ShowSupportWindow();
|
||||
}
|
||||
|
||||
public void OnStateExited(LobbyState state)
|
||||
{
|
||||
if (_supportWindow == null)
|
||||
return;
|
||||
|
||||
_supportWindow.OnClose -= OnWindowClosed;
|
||||
_supportWindow.Dispose();
|
||||
_supportWindow = null;
|
||||
}
|
||||
|
||||
private void ShowSupportWindow()
|
||||
{
|
||||
if (_supportWindow != null)
|
||||
return;
|
||||
|
||||
_supportWindow = UIManager.CreateWindow<PatronSupportWindow>();
|
||||
_supportWindow.OnClose += OnWindowClosed;
|
||||
|
||||
_supportWindow.PatreonButton.OnPressed += _ =>
|
||||
{
|
||||
var patreonLink = _cfg.GetCVar(CCVars.InfoLinksPatreon);
|
||||
if (!string.IsNullOrEmpty(patreonLink))
|
||||
_uriOpener.OpenUri(new Uri(patreonLink));
|
||||
_supportWindow?.Close();
|
||||
};
|
||||
|
||||
_supportWindow.OpenCenteredLeft();
|
||||
}
|
||||
|
||||
private void OnWindowClosed()
|
||||
{
|
||||
_cfg.SetCVar(GoobCVars.PatronSupportLastShown, DateTime.UtcNow.ToString("O"));
|
||||
_cfg.SaveToFile();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
<ui:FancyWindow
|
||||
xmlns="https://spacestation14.io"
|
||||
xmlns:ui="clr-namespace:Content.Client.UserInterface.Controls;assembly=Content.Client"
|
||||
xmlns:controls="clr-namespace:Content.Client._Goobstation.Patron"
|
||||
xmlns:cc="clr-namespace:Content.Client.Administration.UI.CustomControls;assembly=Content.Client"
|
||||
xmlns:maths="clr-namespace:Robust.Shared.Maths;assembly=Robust.Shared.Maths"
|
||||
Title="{Loc 'patron-support-window-title'}"
|
||||
MinSize="555 300"
|
||||
SetSize="555 400">
|
||||
<BoxContainer Orientation="Vertical">
|
||||
<PanelContainer StyleClasses="AngleRect">
|
||||
<BoxContainer Orientation="Vertical" Margin="10 8" HorizontalExpand="True">
|
||||
<Label Text="{Loc 'patron-support-window-header'}"
|
||||
StyleClasses="LabelHeadingBigger" />
|
||||
<Control MinSize="0 8" />
|
||||
<RichTextLabel Text="{Loc 'patron-support-window-description1'}"
|
||||
HorizontalExpand="True" />
|
||||
<Control MinSize="0 4" />
|
||||
<RichTextLabel Text="{Loc 'patron-support-window-description2'}"
|
||||
HorizontalExpand="True" />
|
||||
</BoxContainer>
|
||||
</PanelContainer>
|
||||
|
||||
<Control MinSize="0 4" />
|
||||
|
||||
<BoxContainer Orientation="Vertical" VerticalExpand="True">
|
||||
<ui:NanoHeading Text="{Loc 'patron-support-window-tiers-header'}" />
|
||||
<Control MinSize="0 4" />
|
||||
|
||||
<ScrollContainer HorizontalExpand="True" VerticalExpand="True">
|
||||
<BoxContainer Orientation="Vertical" SeparationOverride="10" Margin="8 4">
|
||||
<PanelContainer StyleClasses="AngleRect" HorizontalExpand="True">
|
||||
<BoxContainer Orientation="Vertical" Margin="8 6" HorizontalExpand="True">
|
||||
<Label Text="{Loc 'patron-support-window-tier1-name'}" StyleClasses="LabelHeading" />
|
||||
<cc:HSeparator />
|
||||
<Control MinSize="0 2" />
|
||||
<RichTextLabel Text="{Loc 'patron-support-window-tier1-perk1'}" HorizontalExpand="True" />
|
||||
<RichTextLabel Text="{Loc 'patron-support-window-tier1-perk2'}" HorizontalExpand="True" />
|
||||
<RichTextLabel Text="{Loc 'patron-support-window-tier1-perk3'}" HorizontalExpand="True" />
|
||||
<RichTextLabel Text="{Loc 'patron-support-window-tier1-perk4'}" HorizontalExpand="True" />
|
||||
<RichTextLabel Text="{Loc 'patron-support-window-tier1-perk5'}" HorizontalExpand="True" />
|
||||
<RichTextLabel Text="{Loc 'patron-support-window-tier1-perk6'}" HorizontalExpand="True" />
|
||||
</BoxContainer>
|
||||
</PanelContainer>
|
||||
|
||||
<PanelContainer StyleClasses="AngleRect" HorizontalExpand="True">
|
||||
<BoxContainer Orientation="Vertical" Margin="8 6" HorizontalExpand="True">
|
||||
<Label Text="{Loc 'patron-support-window-tier2-name'}" StyleClasses="LabelHeading" />
|
||||
<cc:HSeparator />
|
||||
<Control MinSize="0 2" />
|
||||
<RichTextLabel Text="{Loc 'patron-support-window-tier2-perk1'}" HorizontalExpand="True" />
|
||||
<RichTextLabel Text="{Loc 'patron-support-window-tier2-perk2'}" HorizontalExpand="True" />
|
||||
</BoxContainer>
|
||||
</PanelContainer>
|
||||
|
||||
<PanelContainer StyleClasses="AngleRect" HorizontalExpand="True">
|
||||
<BoxContainer Orientation="Vertical" Margin="8 6" HorizontalExpand="True">
|
||||
<Label Text="{Loc 'patron-support-window-tier3-name'}" StyleClasses="LabelHeading" />
|
||||
<cc:HSeparator />
|
||||
<Control MinSize="0 2" />
|
||||
<RichTextLabel Text="{Loc 'patron-support-window-tier3-perk1'}" HorizontalExpand="True" />
|
||||
<RichTextLabel Text="{Loc 'patron-support-window-tier3-perk2'}" HorizontalExpand="True" />
|
||||
</BoxContainer>
|
||||
</PanelContainer>
|
||||
|
||||
<PanelContainer StyleClasses="AngleRect" HorizontalExpand="True">
|
||||
<BoxContainer Orientation="Vertical" Margin="8 6" HorizontalExpand="True">
|
||||
<Label Text="{Loc 'patron-support-window-tier4-name'}" StyleClasses="LabelHeading" />
|
||||
<cc:HSeparator />
|
||||
<Control MinSize="0 2" />
|
||||
<RichTextLabel Text="{Loc 'patron-support-window-tier4-perk1'}" HorizontalExpand="True" />
|
||||
<RichTextLabel Text="{Loc 'patron-support-window-tier4-perk2'}" HorizontalExpand="True" />
|
||||
</BoxContainer>
|
||||
</PanelContainer>
|
||||
|
||||
<PanelContainer StyleClasses="AngleRect" HorizontalExpand="True">
|
||||
<BoxContainer Orientation="Vertical" Margin="8 6" HorizontalExpand="True">
|
||||
<Label Text="{Loc 'patron-support-window-tier5-name'}" StyleClasses="LabelHeading" />
|
||||
<cc:HSeparator />
|
||||
<Control MinSize="0 2" />
|
||||
<RichTextLabel Text="{Loc 'patron-support-window-tier5-perk1'}" HorizontalExpand="True" />
|
||||
<RichTextLabel Text="{Loc 'patron-support-window-tier5-perk2'}" HorizontalExpand="True" />
|
||||
</BoxContainer>
|
||||
</PanelContainer>
|
||||
</BoxContainer>
|
||||
</ScrollContainer>
|
||||
</BoxContainer>
|
||||
|
||||
<Control MinSize="0 4" />
|
||||
|
||||
<ui:StripeBack>
|
||||
<BoxContainer Orientation="Horizontal" HorizontalAlignment="Center" Margin="6 4">
|
||||
<Button Name="PatreonButton" Access="Public" Text="{Loc 'patron-support-window-button'}" StyleClasses="ButtonBig" MinWidth="260" />
|
||||
</BoxContainer>
|
||||
</ui:StripeBack>
|
||||
</BoxContainer>
|
||||
</ui:FancyWindow>
|
||||
@@ -0,0 +1,14 @@
|
||||
using Content.Client.UserInterface.Controls;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
|
||||
namespace Content.Client._Goobstation.Patron;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class PatronSupportWindow : FancyWindow
|
||||
{
|
||||
public PatronSupportWindow()
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Content.Shared.StatusIcon;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.RichText;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Client._Goobstation.UserInterface;
|
||||
|
||||
public sealed class IconTag : IMarkupTag
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||
[Dependency] private readonly IEntitySystemManager _entitySystem = default!;
|
||||
private SpriteSystem? _spriteSystem;
|
||||
|
||||
public string Name => "icon";
|
||||
|
||||
public bool TryGetControl(MarkupNode node, [NotNullWhen(true)] out Control? control)
|
||||
{
|
||||
if (!node.Attributes.TryGetValue("src", out var id) || id.StringValue == null)
|
||||
{
|
||||
control = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
_spriteSystem ??= _entitySystem.GetEntitySystem<SpriteSystem>();
|
||||
var texture = _prototype.TryIndex<JobIconPrototype>(id.StringValue, out var iconPrototype)
|
||||
? _spriteSystem.Frame0(iconPrototype.Icon)
|
||||
: null;
|
||||
|
||||
var icon = new TextureRect
|
||||
{
|
||||
Texture = texture,
|
||||
SetWidth = 20,
|
||||
SetHeight = 20,
|
||||
Stretch = TextureRect.StretchMode.Scale,
|
||||
MouseFilter = Control.MouseFilterMode.Stop,
|
||||
};
|
||||
|
||||
if (node.Attributes.TryGetValue("tooltip", out var tooltip) && tooltip.StringValue != null)
|
||||
icon.ToolTip = tooltip.StringValue;
|
||||
|
||||
control = icon;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@ using Robust.Shared.Timing;
|
||||
using Robust.Shared.Utility;
|
||||
using DependencyAttribute = Robust.Shared.IoC.DependencyAttribute;
|
||||
|
||||
namespace Content.Goobstation.Client.Audio;
|
||||
namespace Content.Client._Goobstation.Audio;
|
||||
|
||||
/// <summary>
|
||||
/// Handles making sounds 'echo' in large, open spaces. Uses simplified raytracing.
|
||||
|
||||
@@ -11,7 +11,7 @@ using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Utility;
|
||||
using DependencyAttribute = Robust.Shared.IoC.DependencyAttribute;
|
||||
|
||||
namespace Content.Goobstation.Client.Audio;
|
||||
namespace Content.Client._Goobstation.Audio;
|
||||
|
||||
/// <summary>
|
||||
/// Handler for client-side audio effects.
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
using Content.Shared._RMC14.GhostColor;
|
||||
using Robust.Client.GameObjects;
|
||||
|
||||
namespace Content.Client._RMC14.GhostColor;
|
||||
|
||||
public sealed class GhostColorSystem : EntitySystem
|
||||
{
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
var defaultColor = Color.FromHex("#FFFFFF88");
|
||||
var colors = EntityQueryEnumerator<GhostColorComponent, SpriteComponent>();
|
||||
while (colors.MoveNext(out var color, out var sprite))
|
||||
{
|
||||
sprite.Color = color.Color ?? defaultColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
using Content.Shared._RMC14.LinkAccount;
|
||||
using Robust.Shared.Network;
|
||||
|
||||
namespace Content.Client._RMC14.LinkAccount;
|
||||
|
||||
public sealed class LinkAccountManager : IPostInjectInit
|
||||
{
|
||||
[Dependency] private readonly INetManager _net = default!;
|
||||
|
||||
private readonly List<SharedRMCPatron> _allPatrons = [];
|
||||
|
||||
public SharedRMCPatronTier? Tier { get; private set; }
|
||||
public bool Linked { get; private set; }
|
||||
public Color? GhostColor { get; private set; }
|
||||
public SharedRMCLobbyMessage? LobbyMessage { get; private set; }
|
||||
public SharedRMCRoundEndShoutouts? RoundEndShoutout { get; private set; }
|
||||
|
||||
public event Action<Guid>? CodeReceived;
|
||||
public event Action? Updated;
|
||||
|
||||
private void OnCode(LinkAccountCodeMsg message)
|
||||
{
|
||||
CodeReceived?.Invoke(message.Code);
|
||||
}
|
||||
|
||||
private void OnStatus(LinkAccountStatusMsg ev)
|
||||
{
|
||||
Tier = ev.Patron?.Tier;
|
||||
Linked = ev.Patron?.Linked ?? false;
|
||||
GhostColor = ev.Patron?.GhostColor;
|
||||
LobbyMessage = ev.Patron?.LobbyMessage;
|
||||
RoundEndShoutout = ev.Patron?.RoundEndShoutout;
|
||||
Updated?.Invoke();
|
||||
}
|
||||
|
||||
private void OnPatronList(RMCPatronListMsg ev)
|
||||
{
|
||||
_allPatrons.Clear();
|
||||
_allPatrons.AddRange(ev.Patrons);
|
||||
}
|
||||
|
||||
public IReadOnlyList<SharedRMCPatron> GetPatrons()
|
||||
{
|
||||
return _allPatrons;
|
||||
}
|
||||
|
||||
public bool CanViewPatronPerks()
|
||||
{
|
||||
return Tier is { } tier && (tier.GhostColor || tier.LobbyMessage || tier.RoundEndShoutout);
|
||||
}
|
||||
|
||||
void IPostInjectInit.PostInject()
|
||||
{
|
||||
_net.RegisterNetMessage<LinkAccountCodeMsg>(OnCode);
|
||||
_net.RegisterNetMessage<LinkAccountRequestMsg>();
|
||||
_net.RegisterNetMessage<LinkAccountStatusMsg>(OnStatus);
|
||||
_net.RegisterNetMessage<RMCPatronListMsg>(OnPatronList);
|
||||
_net.RegisterNetMessage<RMCClearGhostColorMsg>();
|
||||
_net.RegisterNetMessage<RMCChangeGhostColorMsg>();
|
||||
_net.RegisterNetMessage<RMCChangeLobbyMessageMsg>();
|
||||
_net.RegisterNetMessage<RMCChangeNTShoutoutMsg>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using Content.Shared._RMC14.LinkAccount;
|
||||
|
||||
namespace Content.Client._RMC14.LinkAccount;
|
||||
|
||||
public sealed class LinkAccountSystem : EntitySystem
|
||||
{
|
||||
public event Action<SharedRMCDisplayLobbyMessageEvent>? LobbyMessageReceived;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeNetworkEvent<SharedRMCDisplayLobbyMessageEvent>(OnDisplayLobbyMessage);
|
||||
}
|
||||
|
||||
private void OnDisplayLobbyMessage(SharedRMCDisplayLobbyMessageEvent ev)
|
||||
{
|
||||
LobbyMessageReceived?.Invoke(ev);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,249 @@
|
||||
using Content.Client.Lobby.UI;
|
||||
using Content.Client.Message;
|
||||
using Content.Shared._Goobstation.CCVars;
|
||||
using Content.Shared._RMC14.LinkAccount;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controllers;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.Utility;
|
||||
using static Robust.Client.UserInterface.Controls.BaseButton;
|
||||
using static Robust.Client.UserInterface.Controls.LineEdit;
|
||||
using static Robust.Client.UserInterface.Controls.TabContainer;
|
||||
|
||||
namespace Content.Client._RMC14.LinkAccount;
|
||||
|
||||
public sealed class LinkAccountUIController : UIController, IOnSystemChanged<LinkAccountSystem>
|
||||
{
|
||||
[Dependency] private readonly IClipboardManager _clipboard = default!;
|
||||
[Dependency] private readonly IConfigurationManager _config = default!;
|
||||
[Dependency] private readonly LinkAccountManager _linkAccount = default!;
|
||||
[Dependency] private readonly INetManager _net = default!;
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
[Dependency] private readonly IUriOpener _uriOpener = default!;
|
||||
|
||||
private LinkAccountWindow? _window;
|
||||
private PatronPerksWindow? _patronPerksWindow;
|
||||
private TimeSpan _disableUntil;
|
||||
|
||||
private Guid _code;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
_linkAccount.CodeReceived += OnCode;
|
||||
_linkAccount.Updated += OnUpdated;
|
||||
}
|
||||
|
||||
private void OnCode(Guid code)
|
||||
{
|
||||
_code = code;
|
||||
|
||||
if (_window == null)
|
||||
return;
|
||||
|
||||
_window.CopyButton.Disabled = false;
|
||||
}
|
||||
|
||||
private void OnUpdated()
|
||||
{
|
||||
if (UIManager.ActiveScreen is not LobbyGui gui)
|
||||
return;
|
||||
|
||||
gui.CharacterPreview.PatronPerks.Visible = _linkAccount.CanViewPatronPerks();
|
||||
}
|
||||
|
||||
private void OnLobbyMessageReceived(SharedRMCDisplayLobbyMessageEvent message)
|
||||
{
|
||||
if (UIManager.ActiveScreen is not LobbyGui gui)
|
||||
return;
|
||||
|
||||
var user = FormattedMessage.EscapeText(message.User);
|
||||
var msg = FormattedMessage.EscapeText(message.Message);
|
||||
gui.LobbyMessageLabel.SetMarkupPermissive($"[font size=20]Lobby message by: {user}\n{msg}[/font]");
|
||||
}
|
||||
|
||||
public void ToggleWindow()
|
||||
{
|
||||
if (_window == null)
|
||||
{
|
||||
_window = new LinkAccountWindow();
|
||||
_window.OnClose += () => _window = null;
|
||||
_window.Label.SetMarkupPermissive($"{Loc.GetString("rmc-ui-link-discord-account-text")}");
|
||||
if (_linkAccount.Linked)
|
||||
_window.Label.SetMarkupPermissive($"{Loc.GetString("rmc-ui-link-discord-account-already-linked")}\n\n{Loc.GetString("rmc-ui-link-discord-account-text")}");
|
||||
|
||||
_window.CopyButton.OnPressed += _ =>
|
||||
{
|
||||
_clipboard.SetText(_code.ToString());
|
||||
_window.CopyButton.Text = Loc.GetString("rmc-ui-link-discord-account-copied");
|
||||
_window.CopyButton.Disabled = true;
|
||||
_disableUntil = _timing.RealTime.Add(TimeSpan.FromSeconds(3));
|
||||
};
|
||||
|
||||
var messageLink = _config.GetCVar(GoobCVars.RMCDiscordAccountLinkingMessageLink);
|
||||
if (string.IsNullOrEmpty(messageLink))
|
||||
{
|
||||
_window.LinkButton.Visible = false;
|
||||
_window.CopyButton.RemoveStyleClass("OpenRight");
|
||||
}
|
||||
else
|
||||
{
|
||||
_window.LinkButton.Visible = true;
|
||||
_window.LinkButton.OnPressed += _ => _uriOpener.OpenUri(messageLink);
|
||||
_window.CopyButton.AddStyleClass("OpenRight");
|
||||
}
|
||||
|
||||
_window.OpenCentered();
|
||||
|
||||
if (_code == default)
|
||||
_window.CopyButton.Disabled = true;
|
||||
|
||||
_net.ClientSendMessage(new LinkAccountRequestMsg());
|
||||
return;
|
||||
}
|
||||
|
||||
_window.Close();
|
||||
_window = null;
|
||||
}
|
||||
|
||||
public void TogglePatronPerksWindow()
|
||||
{
|
||||
if (_patronPerksWindow == null)
|
||||
{
|
||||
_patronPerksWindow = new PatronPerksWindow();
|
||||
_patronPerksWindow.OnClose += () => _patronPerksWindow = null;
|
||||
|
||||
var tier = _linkAccount.Tier;
|
||||
SetTabTitle(_patronPerksWindow.LobbyMessageTab, Loc.GetString("rmc-ui-lobby-message"));
|
||||
SetTabVisible(_patronPerksWindow.LobbyMessageTab, tier is { LobbyMessage: true });
|
||||
_patronPerksWindow.LobbyMessageSaveButton.OnPressed += OnLobbyMessageSave;
|
||||
|
||||
if (_linkAccount.LobbyMessage?.Message is { } lobbyMessage)
|
||||
_patronPerksWindow.LobbyMessage.Text = lobbyMessage;
|
||||
|
||||
SetTabTitle(_patronPerksWindow.ShoutoutTab, Loc.GetString("rmc-ui-shoutout"));
|
||||
SetTabVisible(_patronPerksWindow.ShoutoutTab, tier is { RoundEndShoutout: true });
|
||||
_patronPerksWindow.NTShoutoutSaveButton.OnPressed += OnNTShoutoutSave;
|
||||
|
||||
if (_linkAccount.RoundEndShoutout?.NT is { } ntShoutout)
|
||||
_patronPerksWindow.NTShoutout.Text = ntShoutout;
|
||||
|
||||
SetTabTitle(_patronPerksWindow.GhostColorTab, Loc.GetString("rmc-ui-ghost-color"));
|
||||
SetTabVisible(_patronPerksWindow.GhostColorTab, tier is { GhostColor: true });
|
||||
_patronPerksWindow.GhostColorSliders.Color = _linkAccount.GhostColor ?? Color.White;
|
||||
_patronPerksWindow.GhostColorSliders.OnColorChanged += OnGhostColorChanged;
|
||||
_patronPerksWindow.GhostColorClearButton.OnPressed += OnGhostColorClear;
|
||||
_patronPerksWindow.GhostColorSaveButton.OnPressed += OnGhostColorSave;
|
||||
|
||||
UpdateExamples();
|
||||
|
||||
for (var i = 0; i < _patronPerksWindow.Tabs.ChildCount; i++)
|
||||
{
|
||||
var child = _patronPerksWindow.Tabs.GetChild(i);
|
||||
if (!child.GetValue(TabVisibleProperty))
|
||||
continue;
|
||||
|
||||
_patronPerksWindow.Tabs.CurrentTab = i;
|
||||
break;
|
||||
}
|
||||
|
||||
_patronPerksWindow.OpenCentered();
|
||||
return;
|
||||
}
|
||||
|
||||
_patronPerksWindow.Close();
|
||||
_patronPerksWindow = null;
|
||||
}
|
||||
|
||||
private void OnLobbyMessageSave(ButtonEventArgs args)
|
||||
{
|
||||
var text = _patronPerksWindow?.LobbyMessage.Text;
|
||||
if (text == null)
|
||||
return;
|
||||
|
||||
if (text.Length > SharedRMCLobbyMessage.CharacterLimit)
|
||||
{
|
||||
text = text[..SharedRMCLobbyMessage.CharacterLimit];
|
||||
_patronPerksWindow?.LobbyMessage.SetText(text, false);
|
||||
}
|
||||
|
||||
_net.ClientSendMessage(new RMCChangeLobbyMessageMsg { Text = text });
|
||||
}
|
||||
|
||||
private void OnNTShoutoutSave(ButtonEventArgs args)
|
||||
{
|
||||
var text = _patronPerksWindow?.NTShoutout.Text;
|
||||
if (text == null)
|
||||
return;
|
||||
|
||||
if (text.Length > SharedRMCRoundEndShoutouts.CharacterLimit)
|
||||
{
|
||||
text = text[..SharedRMCRoundEndShoutouts.CharacterLimit];
|
||||
_patronPerksWindow?.NTShoutout.SetText(text, false);
|
||||
}
|
||||
|
||||
_net.ClientSendMessage(new RMCChangeNTShoutoutMsg { Name = text });
|
||||
UpdateExamples();
|
||||
}
|
||||
|
||||
private void OnGhostColorChanged(Color color)
|
||||
{
|
||||
if (_patronPerksWindow is not { IsOpen: true })
|
||||
return;
|
||||
|
||||
_patronPerksWindow.GhostColorSaveButton.Disabled = false;
|
||||
}
|
||||
|
||||
private void OnGhostColorClear(ButtonEventArgs args)
|
||||
{
|
||||
if (_patronPerksWindow is not { IsOpen: true })
|
||||
return;
|
||||
|
||||
_patronPerksWindow.GhostColorSliders.Color = Color.White;
|
||||
_net.ClientSendMessage(new RMCClearGhostColorMsg());
|
||||
}
|
||||
|
||||
private void OnGhostColorSave(ButtonEventArgs args)
|
||||
{
|
||||
if (_patronPerksWindow is not { IsOpen: true })
|
||||
return;
|
||||
|
||||
_net.ClientSendMessage(new RMCChangeGhostColorMsg { Color = _patronPerksWindow.GhostColorSliders.Color });
|
||||
}
|
||||
|
||||
private void UpdateExamples()
|
||||
{
|
||||
if (_patronPerksWindow == null)
|
||||
return;
|
||||
|
||||
var nt = _patronPerksWindow.NTShoutout.Text.Trim();
|
||||
_patronPerksWindow.NTShoutoutExample.SetMarkupPermissive(string.IsNullOrWhiteSpace(nt)
|
||||
? " "
|
||||
: $"{Loc.GetString("rmc-ui-shoutout-example")} {Loc.GetString("rmc-ui-shoutout-nt", ("name", nt))}");
|
||||
}
|
||||
|
||||
public void OnSystemLoaded(LinkAccountSystem system)
|
||||
{
|
||||
system.LobbyMessageReceived += OnLobbyMessageReceived;
|
||||
}
|
||||
|
||||
public void OnSystemUnloaded(LinkAccountSystem system)
|
||||
{
|
||||
system.LobbyMessageReceived -= OnLobbyMessageReceived;
|
||||
}
|
||||
|
||||
public override void FrameUpdate(FrameEventArgs args)
|
||||
{
|
||||
if (_window == null)
|
||||
return;
|
||||
|
||||
var time = _timing.RealTime;
|
||||
if (_disableUntil != default && time > _disableUntil)
|
||||
{
|
||||
_disableUntil = default;
|
||||
_window.CopyButton.Text = Loc.GetString("rmc-ui-link-discord-account-copy");
|
||||
_window.CopyButton.Disabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<linkAccount:LinkAccountWindow
|
||||
xmlns="https://spacestation14.io"
|
||||
xmlns:linkAccount="clr-namespace:Content.Client._RMC14.LinkAccount"
|
||||
Title="{Loc 'rmc-ui-link-discord-account'}">
|
||||
<BoxContainer Orientation="Vertical">
|
||||
<RichTextLabel Name="Label" Access="Public" Margin="0 0 0 5" />
|
||||
<BoxContainer Orientation="Horizontal" HorizontalAlignment="Center"
|
||||
HorizontalExpand="True">
|
||||
<Button Name="CopyButton" Access="Public" StyleClasses="OpenRight"
|
||||
Text="{Loc 'rmc-ui-link-discord-account-copy'}" HorizontalExpand="True" />
|
||||
<Button Name="LinkButton" Access="Public" StyleClasses="OpenLeft"
|
||||
Text="{Loc 'rmc-ui-link-discord-account-open-channel'}"
|
||||
HorizontalExpand="True" />
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
</linkAccount:LinkAccountWindow>
|
||||
@@ -0,0 +1,15 @@
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
|
||||
namespace Content.Client._RMC14.LinkAccount;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class LinkAccountWindow : DefaultWindow
|
||||
{
|
||||
public LinkAccountWindow()
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<controls:PatronPerksWindow
|
||||
xmlns="https://spacestation14.io"
|
||||
xmlns:controls="clr-namespace:Content.Client._RMC14.LinkAccount"
|
||||
xmlns:cc="clr-namespace:Content.Client.Administration.UI.CustomControls"
|
||||
Title="{Loc 'rmc-ui-patron-perks'}"
|
||||
MinSize="625 475">
|
||||
<TabContainer Name="Tabs" Access="Public">
|
||||
<BoxContainer Name="LobbyMessageTab" Access="Public" Orientation="Vertical" Margin="5">
|
||||
<Label Text="{Loc 'rmc-ui-lobby-message-description'}" />
|
||||
<LineEdit Name="LobbyMessage" Access="Public" Margin="0 10 0 0" />
|
||||
<Button Name="LobbyMessageSaveButton" Access="Public" Text="{Loc 'rmc-ui-save'}" />
|
||||
</BoxContainer>
|
||||
<BoxContainer Name="ShoutoutTab" Access="Public" Orientation="Vertical" Visible="False"
|
||||
Margin="5">
|
||||
<BoxContainer Access="Public" Orientation="Vertical">
|
||||
<Label Text="{Loc 'rmc-ui-shoutout-nt-title'}" />
|
||||
<Label Text="{Loc 'rmc-ui-shoutout-nt-description'}" />
|
||||
<RichTextLabel Name="NTShoutoutExample" Access="Public" />
|
||||
<LineEdit Name="NTShoutout" Access="Public" Margin="0 10 0 0" />
|
||||
<Button Name="NTShoutoutSaveButton" Access="Public" Text="{Loc 'rmc-ui-save'}" />
|
||||
</BoxContainer>
|
||||
<cc:HSeparator Margin="0 15" />
|
||||
<Label Text="{Loc 'rmc-ui-shoutout-info'}" />
|
||||
</BoxContainer>
|
||||
<BoxContainer Name="GhostColorTab" Access="Public" Orientation="Vertical" Margin="5">
|
||||
<Label Text="{Loc 'rmc-ui-ghost-color'}" />
|
||||
<ColorSelectorSliders Name="GhostColorSliders" Access="Public" Margin="0 10 0 0" />
|
||||
<Button Name="GhostColorClearButton" Access="Public" Text="{Loc 'rmc-ui-ghost-color-clear'}" />
|
||||
<Button Name="GhostColorSaveButton" Access="Public" Text="{Loc 'rmc-ui-save'}"
|
||||
Disabled="True" />
|
||||
</BoxContainer>
|
||||
</TabContainer>
|
||||
</controls:PatronPerksWindow>
|
||||
@@ -0,0 +1,15 @@
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
|
||||
namespace Content.Client._RMC14.LinkAccount;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class PatronPerksWindow : DefaultWindow
|
||||
{
|
||||
public PatronPerksWindow()
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ using CsvHelper;
|
||||
using CsvHelper.Configuration;
|
||||
using static System.Environment;
|
||||
|
||||
var repository = new DirectoryInfo(Directory.GetCurrentDirectory()).Parent!.Parent!.Parent!.Parent!;
|
||||
var repository = new DirectoryInfo(Directory.GetCurrentDirectory());
|
||||
var patronsPath = Path.Combine(repository.FullName, "Resources/Credits/Patrons.yml");
|
||||
if (!File.Exists(patronsPath))
|
||||
{
|
||||
|
||||
+2097
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,117 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Content.Server.Database.Migrations.Postgres
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class RMCPatrons : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "rmc_discord_accounts",
|
||||
columns: table => new
|
||||
{
|
||||
rmc_discord_accounts_id = table.Column<decimal>(type: "numeric(20,0)", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_rmc_discord_accounts", x => x.rmc_discord_accounts_id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "rmc_patron_tiers",
|
||||
columns: table => new
|
||||
{
|
||||
rmc_patron_tiers_id = table.Column<int>(type: "integer", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
show_on_credits = table.Column<bool>(type: "boolean", nullable: false),
|
||||
lobby_message = table.Column<bool>(type: "boolean", nullable: false),
|
||||
round_end_shoutout = table.Column<bool>(type: "boolean", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_rmc_patron_tiers", x => x.rmc_patron_tiers_id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "rmc_linked_accounts",
|
||||
columns: table => new
|
||||
{
|
||||
player_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
discord_id = table.Column<decimal>(type: "numeric(20,0)", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_rmc_linked_accounts", x => x.player_id);
|
||||
table.ForeignKey(
|
||||
name: "FK_rmc_linked_accounts_player_player_id",
|
||||
column: x => x.player_id,
|
||||
principalTable: "player",
|
||||
principalColumn: "user_id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_rmc_linked_accounts_rmc_discord_accounts_discord_id",
|
||||
column: x => x.discord_id,
|
||||
principalTable: "rmc_discord_accounts",
|
||||
principalColumn: "rmc_discord_accounts_id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "rmc_patrons",
|
||||
columns: table => new
|
||||
{
|
||||
player_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
tier_id = table.Column<int>(type: "integer", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_rmc_patrons", x => x.player_id);
|
||||
table.ForeignKey(
|
||||
name: "FK_rmc_patrons_player_player_id",
|
||||
column: x => x.player_id,
|
||||
principalTable: "player",
|
||||
principalColumn: "user_id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_rmc_patrons_rmc_patron_tiers_tier_id",
|
||||
column: x => x.tier_id,
|
||||
principalTable: "rmc_patron_tiers",
|
||||
principalColumn: "rmc_patron_tiers_id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_rmc_linked_accounts_discord_id",
|
||||
table: "rmc_linked_accounts",
|
||||
column: "discord_id",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_rmc_patrons_tier_id",
|
||||
table: "rmc_patrons",
|
||||
column: "tier_id");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "rmc_linked_accounts");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "rmc_patrons");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "rmc_discord_accounts");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "rmc_patron_tiers");
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
+2113
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,61 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Content.Server.Database.Migrations.Postgres
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class RMCPatronsRolePriority : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<decimal>(
|
||||
name: "discord_role",
|
||||
table: "rmc_patron_tiers",
|
||||
type: "numeric(20,0)",
|
||||
nullable: false,
|
||||
defaultValue: 0m);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "name",
|
||||
table: "rmc_patron_tiers",
|
||||
type: "text",
|
||||
nullable: false,
|
||||
defaultValue: "");
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "priority",
|
||||
table: "rmc_patron_tiers",
|
||||
type: "integer",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_rmc_patron_tiers_discord_role",
|
||||
table: "rmc_patron_tiers",
|
||||
column: "discord_role",
|
||||
unique: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_rmc_patron_tiers_discord_role",
|
||||
table: "rmc_patron_tiers");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "discord_role",
|
||||
table: "rmc_patron_tiers");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "name",
|
||||
table: "rmc_patron_tiers");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "priority",
|
||||
table: "rmc_patron_tiers");
|
||||
}
|
||||
}
|
||||
}
|
||||
+2152
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Content.Server.Database.Migrations.Postgres
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class RMCPatronsCode : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "rmc_linking_codes",
|
||||
columns: table => new
|
||||
{
|
||||
player_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
code = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
creation_time = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_rmc_linking_codes", x => x.player_id);
|
||||
table.ForeignKey(
|
||||
name: "FK_rmc_linking_codes_player_player_id",
|
||||
column: x => x.player_id,
|
||||
principalTable: "player",
|
||||
principalColumn: "user_id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_rmc_linking_codes_code",
|
||||
table: "rmc_linking_codes",
|
||||
column: "code");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "rmc_linking_codes");
|
||||
}
|
||||
}
|
||||
}
|
||||
+2151
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,22 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Content.Server.Database.Migrations.Postgres
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class RMCPatronsCodeDate : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
+2213
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,65 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Content.Server.Database.Migrations.Postgres
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class RMCLinkedAccountLogs : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "rmc_linked_accounts_logs",
|
||||
columns: table => new
|
||||
{
|
||||
rmc_linked_accounts_logs_id = table.Column<int>(type: "integer", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
player_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
discord_id = table.Column<decimal>(type: "numeric(20,0)", nullable: false),
|
||||
at = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_rmc_linked_accounts_logs", x => x.rmc_linked_accounts_logs_id);
|
||||
table.ForeignKey(
|
||||
name: "FK_rmc_linked_accounts_logs_player__player_id1",
|
||||
column: x => x.player_id,
|
||||
principalTable: "player",
|
||||
principalColumn: "user_id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_rmc_linked_accounts_logs_rmc_discord_accounts_discord_id",
|
||||
column: x => x.discord_id,
|
||||
principalTable: "rmc_discord_accounts",
|
||||
principalColumn: "rmc_discord_accounts_id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_rmc_linked_accounts_logs_at",
|
||||
table: "rmc_linked_accounts_logs",
|
||||
column: "at");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_rmc_linked_accounts_logs_discord_id",
|
||||
table: "rmc_linked_accounts_logs",
|
||||
column: "discord_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_rmc_linked_accounts_logs_player_id",
|
||||
table: "rmc_linked_accounts_logs",
|
||||
column: "player_id");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "rmc_linked_accounts_logs");
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
+2273
File diff suppressed because it is too large
Load Diff
+61
@@ -0,0 +1,61 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Content.Server.Database.Migrations.Postgres
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class RMCPatronLobbyAndRoundEnd : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "rmc_patron_lobby_messages",
|
||||
columns: table => new
|
||||
{
|
||||
patron_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
message = table.Column<string>(type: "character varying(500)", maxLength: 500, nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_rmc_patron_lobby_messages", x => x.patron_id);
|
||||
table.ForeignKey(
|
||||
name: "FK_rmc_patron_lobby_messages_rmc_patrons_patron_id",
|
||||
column: x => x.patron_id,
|
||||
principalTable: "rmc_patrons",
|
||||
principalColumn: "player_id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "rmc_patron_round_end_nt_shoutouts",
|
||||
columns: table => new
|
||||
{
|
||||
patron_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
name = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_rmc_patron_round_end_nt_shoutouts", x => x.patron_id);
|
||||
table.ForeignKey(
|
||||
name: "FK_rmc_patron_round_end_nt_shoutouts_rmc_patrons_patron_id",
|
||||
column: x => x.patron_id,
|
||||
principalTable: "rmc_patrons",
|
||||
principalColumn: "player_id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "rmc_patron_lobby_messages");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "rmc_patron_round_end_nt_shoutouts");
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
+2349
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,39 @@
|
||||
#nullable disable
|
||||
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace Content.Server.Database.Migrations.Postgres
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class RMCPatronsGhostColor : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "ghost_color",
|
||||
table: "rmc_patrons",
|
||||
type: "integer",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "ghost_color",
|
||||
table: "rmc_patron_tiers",
|
||||
type: "boolean",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "ghost_color",
|
||||
table: "rmc_patrons");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "ghost_color",
|
||||
table: "rmc_patron_tiers");
|
||||
}
|
||||
}
|
||||
}
|
||||
+2471
File diff suppressed because it is too large
Load Diff
+36
@@ -0,0 +1,36 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Content.Server.Database.Migrations.Postgres
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class RMCPatronButItDoesntSpamTheDatabase : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_rmc_patron_tiers_lobby_message",
|
||||
table: "rmc_patron_tiers",
|
||||
column: "lobby_message");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_rmc_patron_tiers_round_end_shoutout",
|
||||
table: "rmc_patron_tiers",
|
||||
column: "round_end_shoutout");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_rmc_patron_tiers_lobby_message",
|
||||
table: "rmc_patron_tiers");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_rmc_patron_tiers_round_end_shoutout",
|
||||
table: "rmc_patron_tiers");
|
||||
}
|
||||
}
|
||||
}
|
||||
+2480
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,28 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Content.Server.Database.Migrations.Postgres
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class PatronIcons : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "icon",
|
||||
table: "rmc_patron_tiers",
|
||||
type: "text",
|
||||
nullable: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "icon",
|
||||
table: "rmc_patron_tiers");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1021,6 +1021,213 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
b.ToTable("profile_role_loadout", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.RMCDiscordAccount", b =>
|
||||
{
|
||||
b.Property<decimal>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("numeric(20,0)")
|
||||
.HasColumnName("rmc_discord_accounts_id");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_rmc_discord_accounts");
|
||||
|
||||
b.ToTable("rmc_discord_accounts", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.RMCLinkedAccount", b =>
|
||||
{
|
||||
b.Property<Guid>("PlayerId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("player_id");
|
||||
|
||||
b.Property<decimal>("DiscordId")
|
||||
.HasColumnType("numeric(20,0)")
|
||||
.HasColumnName("discord_id");
|
||||
|
||||
b.HasKey("PlayerId")
|
||||
.HasName("PK_rmc_linked_accounts");
|
||||
|
||||
b.HasIndex("DiscordId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("rmc_linked_accounts", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.RMCLinkedAccountLogs", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("rmc_linked_accounts_logs_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<DateTime>("At")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("at");
|
||||
|
||||
b.Property<decimal>("DiscordId")
|
||||
.HasColumnType("numeric(20,0)")
|
||||
.HasColumnName("discord_id");
|
||||
|
||||
b.Property<Guid>("PlayerId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("player_id");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_rmc_linked_accounts_logs");
|
||||
|
||||
b.HasIndex("At")
|
||||
.HasDatabaseName("IX_rmc_linked_accounts_logs_at");
|
||||
|
||||
b.HasIndex("DiscordId")
|
||||
.HasDatabaseName("IX_rmc_linked_accounts_logs_discord_id");
|
||||
|
||||
b.HasIndex("PlayerId")
|
||||
.HasDatabaseName("IX_rmc_linked_accounts_logs_player_id");
|
||||
|
||||
b.ToTable("rmc_linked_accounts_logs", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.RMCLinkingCodes", b =>
|
||||
{
|
||||
b.Property<Guid>("PlayerId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("player_id");
|
||||
|
||||
b.Property<Guid>("Code")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("code");
|
||||
|
||||
b.Property<DateTime>("CreationTime")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("creation_time");
|
||||
|
||||
b.HasKey("PlayerId")
|
||||
.HasName("PK_rmc_linking_codes");
|
||||
|
||||
b.HasIndex("Code")
|
||||
.HasDatabaseName("IX_rmc_linking_codes_code");
|
||||
|
||||
b.ToTable("rmc_linking_codes", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.RMCPatron", b =>
|
||||
{
|
||||
b.Property<Guid>("PlayerId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("player_id");
|
||||
|
||||
b.Property<int?>("GhostColor")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("ghost_color");
|
||||
|
||||
b.Property<int>("TierId")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("tier_id");
|
||||
|
||||
b.HasKey("PlayerId")
|
||||
.HasName("PK_rmc_patrons");
|
||||
|
||||
b.HasIndex("TierId")
|
||||
.HasDatabaseName("IX_rmc_patrons_tier_id");
|
||||
|
||||
b.ToTable("rmc_patrons", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.RMCPatronLobbyMessage", b =>
|
||||
{
|
||||
b.Property<Guid>("PatronId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("patron_id");
|
||||
|
||||
b.Property<string>("Message")
|
||||
.IsRequired()
|
||||
.HasMaxLength(500)
|
||||
.HasColumnType("character varying(500)")
|
||||
.HasColumnName("message");
|
||||
|
||||
b.HasKey("PatronId")
|
||||
.HasName("PK_rmc_patron_lobby_messages");
|
||||
|
||||
b.ToTable("rmc_patron_lobby_messages", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.RMCPatronRoundEndNTShoutout", b =>
|
||||
{
|
||||
b.Property<Guid>("PatronId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("patron_id");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("character varying(100)")
|
||||
.HasColumnName("name");
|
||||
|
||||
b.HasKey("PatronId")
|
||||
.HasName("PK_rmc_patron_round_end_nt_shoutouts");
|
||||
|
||||
b.ToTable("rmc_patron_round_end_nt_shoutouts", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.RMCPatronTier", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("rmc_patron_tiers_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<decimal>("DiscordRole")
|
||||
.HasColumnType("numeric(20,0)")
|
||||
.HasColumnName("discord_role");
|
||||
|
||||
b.Property<bool>("GhostColor")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("ghost_color");
|
||||
|
||||
b.Property<string>("Icon")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("icon");
|
||||
|
||||
b.Property<bool>("LobbyMessage")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("lobby_message");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("name");
|
||||
|
||||
b.Property<int>("Priority")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("priority");
|
||||
|
||||
b.Property<bool>("RoundEndShoutout")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("round_end_shoutout");
|
||||
|
||||
b.Property<bool>("ShowOnCredits")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("show_on_credits");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_rmc_patron_tiers");
|
||||
|
||||
b.HasIndex("DiscordRole")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("LobbyMessage")
|
||||
.HasDatabaseName("IX_rmc_patron_tiers_lobby_message");
|
||||
|
||||
b.HasIndex("RoundEndShoutout")
|
||||
.HasDatabaseName("IX_rmc_patron_tiers_round_end_shoutout");
|
||||
|
||||
b.ToTable("rmc_patron_tiers", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.RoleWhitelist", b =>
|
||||
{
|
||||
b.Property<Guid>("PlayerUserId")
|
||||
@@ -1811,6 +2018,109 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
b.Navigation("Profile");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.RMCLinkedAccount", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.RMCDiscordAccount", "Discord")
|
||||
.WithOne("LinkedAccount")
|
||||
.HasForeignKey("Content.Server.Database.RMCLinkedAccount", "DiscordId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_rmc_linked_accounts_rmc_discord_accounts_discord_id");
|
||||
|
||||
b.HasOne("Content.Server.Database.Player", "Player")
|
||||
.WithOne("LinkedAccount")
|
||||
.HasForeignKey("Content.Server.Database.RMCLinkedAccount", "PlayerId")
|
||||
.HasPrincipalKey("Content.Server.Database.Player", "UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_rmc_linked_accounts_player_player_id");
|
||||
|
||||
b.Navigation("Discord");
|
||||
|
||||
b.Navigation("Player");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.RMCLinkedAccountLogs", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.RMCDiscordAccount", "Discord")
|
||||
.WithMany("LinkedAccountLogs")
|
||||
.HasForeignKey("DiscordId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_rmc_linked_accounts_logs_rmc_discord_accounts_discord_id");
|
||||
|
||||
b.HasOne("Content.Server.Database.Player", "Player")
|
||||
.WithMany("LinkedAccountLogs")
|
||||
.HasForeignKey("PlayerId")
|
||||
.HasPrincipalKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_rmc_linked_accounts_logs_player__player_id1");
|
||||
|
||||
b.Navigation("Discord");
|
||||
|
||||
b.Navigation("Player");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.RMCLinkingCodes", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Player", "Player")
|
||||
.WithOne("LinkingCodes")
|
||||
.HasForeignKey("Content.Server.Database.RMCLinkingCodes", "PlayerId")
|
||||
.HasPrincipalKey("Content.Server.Database.Player", "UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_rmc_linking_codes_player_player_id");
|
||||
|
||||
b.Navigation("Player");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.RMCPatron", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Player", "Player")
|
||||
.WithOne("Patron")
|
||||
.HasForeignKey("Content.Server.Database.RMCPatron", "PlayerId")
|
||||
.HasPrincipalKey("Content.Server.Database.Player", "UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_rmc_patrons_player_player_id");
|
||||
|
||||
b.HasOne("Content.Server.Database.RMCPatronTier", "Tier")
|
||||
.WithMany("Patrons")
|
||||
.HasForeignKey("TierId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_rmc_patrons_rmc_patron_tiers_tier_id");
|
||||
|
||||
b.Navigation("Player");
|
||||
|
||||
b.Navigation("Tier");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.RMCPatronLobbyMessage", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.RMCPatron", "Patron")
|
||||
.WithOne("LobbyMessage")
|
||||
.HasForeignKey("Content.Server.Database.RMCPatronLobbyMessage", "PatronId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_rmc_patron_lobby_messages_rmc_patrons_patron_id");
|
||||
|
||||
b.Navigation("Patron");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.RMCPatronRoundEndNTShoutout", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.RMCPatron", "Patron")
|
||||
.WithOne("RoundEndNTShoutout")
|
||||
.HasForeignKey("Content.Server.Database.RMCPatronRoundEndNTShoutout", "PatronId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_rmc_patron_round_end_nt_shoutouts_rmc_patrons_patron_id");
|
||||
|
||||
b.Navigation("Patron");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.RoleWhitelist", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Player", "Player")
|
||||
@@ -2081,6 +2391,14 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
b.Navigation("AdminWatchlistsReceived");
|
||||
|
||||
b.Navigation("JobWhitelists");
|
||||
|
||||
b.Navigation("LinkedAccount");
|
||||
|
||||
b.Navigation("LinkedAccountLogs");
|
||||
|
||||
b.Navigation("LinkingCodes");
|
||||
|
||||
b.Navigation("Patron");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Preference", b =>
|
||||
@@ -2109,6 +2427,26 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
b.Navigation("Groups");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.RMCDiscordAccount", b =>
|
||||
{
|
||||
b.Navigation("LinkedAccount")
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("LinkedAccountLogs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.RMCPatron", b =>
|
||||
{
|
||||
b.Navigation("LobbyMessage");
|
||||
|
||||
b.Navigation("RoundEndNTShoutout");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.RMCPatronTier", b =>
|
||||
{
|
||||
b.Navigation("Patrons");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Round", b =>
|
||||
{
|
||||
b.Navigation("AdminLogs");
|
||||
|
||||
+2018
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,117 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Content.Server.Database.Migrations.Sqlite
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class RMCPatrons : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "rmc_discord_accounts",
|
||||
columns: table => new
|
||||
{
|
||||
rmc_discord_accounts_id = table.Column<ulong>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_rmc_discord_accounts", x => x.rmc_discord_accounts_id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "rmc_patron_tiers",
|
||||
columns: table => new
|
||||
{
|
||||
rmc_patron_tiers_id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
show_on_credits = table.Column<bool>(type: "INTEGER", nullable: false),
|
||||
lobby_message = table.Column<bool>(type: "INTEGER", nullable: false),
|
||||
round_end_shoutout = table.Column<bool>(type: "INTEGER", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_rmc_patron_tiers", x => x.rmc_patron_tiers_id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "rmc_linked_accounts",
|
||||
columns: table => new
|
||||
{
|
||||
player_id = table.Column<Guid>(type: "TEXT", nullable: false),
|
||||
discord_id = table.Column<ulong>(type: "INTEGER", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_rmc_linked_accounts", x => x.player_id);
|
||||
table.ForeignKey(
|
||||
name: "FK_rmc_linked_accounts_player_player_id",
|
||||
column: x => x.player_id,
|
||||
principalTable: "player",
|
||||
principalColumn: "user_id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_rmc_linked_accounts_rmc_discord_accounts_discord_id",
|
||||
column: x => x.discord_id,
|
||||
principalTable: "rmc_discord_accounts",
|
||||
principalColumn: "rmc_discord_accounts_id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "rmc_patrons",
|
||||
columns: table => new
|
||||
{
|
||||
player_id = table.Column<Guid>(type: "TEXT", nullable: false),
|
||||
tier_id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_rmc_patrons", x => x.player_id);
|
||||
table.ForeignKey(
|
||||
name: "FK_rmc_patrons_player_player_id",
|
||||
column: x => x.player_id,
|
||||
principalTable: "player",
|
||||
principalColumn: "user_id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_rmc_patrons_rmc_patron_tiers_tier_id",
|
||||
column: x => x.tier_id,
|
||||
principalTable: "rmc_patron_tiers",
|
||||
principalColumn: "rmc_patron_tiers_id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_rmc_linked_accounts_discord_id",
|
||||
table: "rmc_linked_accounts",
|
||||
column: "discord_id",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_rmc_patrons_tier_id",
|
||||
table: "rmc_patrons",
|
||||
column: "tier_id");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "rmc_linked_accounts");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "rmc_patrons");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "rmc_discord_accounts");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "rmc_patron_tiers");
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
+2034
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,61 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Content.Server.Database.Migrations.Sqlite
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class RMCPatronsRolePriority : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<ulong>(
|
||||
name: "discord_role",
|
||||
table: "rmc_patron_tiers",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: 0ul);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "name",
|
||||
table: "rmc_patron_tiers",
|
||||
type: "TEXT",
|
||||
nullable: false,
|
||||
defaultValue: "");
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "priority",
|
||||
table: "rmc_patron_tiers",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_rmc_patron_tiers_discord_role",
|
||||
table: "rmc_patron_tiers",
|
||||
column: "discord_role",
|
||||
unique: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_rmc_patron_tiers_discord_role",
|
||||
table: "rmc_patron_tiers");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "discord_role",
|
||||
table: "rmc_patron_tiers");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "name",
|
||||
table: "rmc_patron_tiers");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "priority",
|
||||
table: "rmc_patron_tiers");
|
||||
}
|
||||
}
|
||||
}
|
||||
+2073
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Content.Server.Database.Migrations.Sqlite
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class RMCPatronsCode : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "rmc_linking_codes",
|
||||
columns: table => new
|
||||
{
|
||||
player_id = table.Column<Guid>(type: "TEXT", nullable: false),
|
||||
code = table.Column<Guid>(type: "TEXT", nullable: false),
|
||||
creation_time = table.Column<DateTime>(type: "TEXT", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_rmc_linking_codes", x => x.player_id);
|
||||
table.ForeignKey(
|
||||
name: "FK_rmc_linking_codes_player_player_id",
|
||||
column: x => x.player_id,
|
||||
principalTable: "player",
|
||||
principalColumn: "user_id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_rmc_linking_codes_code",
|
||||
table: "rmc_linking_codes",
|
||||
column: "code");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "rmc_linking_codes");
|
||||
}
|
||||
}
|
||||
}
|
||||
+2072
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,22 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Content.Server.Database.Migrations.Sqlite
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class RMCPatronsCodeDate : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+2132
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,64 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Content.Server.Database.Migrations.Sqlite
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class RMCLinkedAccountLogs : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "rmc_linked_accounts_logs",
|
||||
columns: table => new
|
||||
{
|
||||
rmc_linked_accounts_logs_id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
player_id = table.Column<Guid>(type: "TEXT", nullable: false),
|
||||
discord_id = table.Column<ulong>(type: "INTEGER", nullable: false),
|
||||
at = table.Column<DateTime>(type: "TEXT", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_rmc_linked_accounts_logs", x => x.rmc_linked_accounts_logs_id);
|
||||
table.ForeignKey(
|
||||
name: "FK_rmc_linked_accounts_logs_player__player_id1",
|
||||
column: x => x.player_id,
|
||||
principalTable: "player",
|
||||
principalColumn: "user_id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_rmc_linked_accounts_logs_rmc_discord_accounts_discord_id",
|
||||
column: x => x.discord_id,
|
||||
principalTable: "rmc_discord_accounts",
|
||||
principalColumn: "rmc_discord_accounts_id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_rmc_linked_accounts_logs_at",
|
||||
table: "rmc_linked_accounts_logs",
|
||||
column: "at");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_rmc_linked_accounts_logs_discord_id",
|
||||
table: "rmc_linked_accounts_logs",
|
||||
column: "discord_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_rmc_linked_accounts_logs_player_id",
|
||||
table: "rmc_linked_accounts_logs",
|
||||
column: "player_id");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "rmc_linked_accounts_logs");
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
+2199
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,61 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Content.Server.Database.Migrations.Sqlite
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class RMCPatronLobbyAndRoundEnd : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "rmc_patron_lobby_messages",
|
||||
columns: table => new
|
||||
{
|
||||
patron_id = table.Column<Guid>(type: "TEXT", nullable: false),
|
||||
message = table.Column<string>(type: "TEXT", maxLength: 500, nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_rmc_patron_lobby_messages", x => x.patron_id);
|
||||
table.ForeignKey(
|
||||
name: "FK_rmc_patron_lobby_messages_rmc_patrons_patron_id",
|
||||
column: x => x.patron_id,
|
||||
principalTable: "rmc_patrons",
|
||||
principalColumn: "player_id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "rmc_patron_round_end_nt_shoutouts",
|
||||
columns: table => new
|
||||
{
|
||||
patron_id = table.Column<Guid>(type: "TEXT", nullable: false),
|
||||
name = table.Column<string>(type: "TEXT", maxLength: 100, nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_rmc_patron_round_end_nt_shoutouts", x => x.patron_id);
|
||||
table.ForeignKey(
|
||||
name: "FK_rmc_patron_round_end_nt_shoutouts_rmc_patrons_patron_id",
|
||||
column: x => x.patron_id,
|
||||
principalTable: "rmc_patrons",
|
||||
principalColumn: "player_id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "rmc_patron_lobby_messages");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "rmc_patron_round_end_nt_shoutouts");
|
||||
}
|
||||
}
|
||||
}
|
||||
+2268
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,39 @@
|
||||
#nullable disable
|
||||
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace Content.Server.Database.Migrations.Sqlite
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class RMCPatronsGhostColor : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "ghost_color",
|
||||
table: "rmc_patrons",
|
||||
type: "INTEGER",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "ghost_color",
|
||||
table: "rmc_patron_tiers",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "ghost_color",
|
||||
table: "rmc_patrons");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "ghost_color",
|
||||
table: "rmc_patron_tiers");
|
||||
}
|
||||
}
|
||||
}
|
||||
+2390
File diff suppressed because it is too large
Load Diff
+36
@@ -0,0 +1,36 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Content.Server.Database.Migrations.Sqlite
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class RMCPatronButItDoesntSpamTheDatabase : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_rmc_patron_tiers_lobby_message",
|
||||
table: "rmc_patron_tiers",
|
||||
column: "lobby_message");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_rmc_patron_tiers_round_end_shoutout",
|
||||
table: "rmc_patron_tiers",
|
||||
column: "round_end_shoutout");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_rmc_patron_tiers_lobby_message",
|
||||
table: "rmc_patron_tiers");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_rmc_patron_tiers_round_end_shoutout",
|
||||
table: "rmc_patron_tiers");
|
||||
}
|
||||
}
|
||||
}
|
||||
+2399
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,28 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Content.Server.Database.Migrations.Sqlite
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class PatronIcons : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "icon",
|
||||
table: "rmc_patron_tiers",
|
||||
type: "TEXT",
|
||||
nullable: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "icon",
|
||||
table: "rmc_patron_tiers");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -967,6 +967,209 @@ namespace Content.Server.Database.Migrations.Sqlite
|
||||
b.ToTable("profile_role_loadout", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.RMCDiscordAccount", b =>
|
||||
{
|
||||
b.Property<ulong>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("rmc_discord_accounts_id");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_rmc_discord_accounts");
|
||||
|
||||
b.ToTable("rmc_discord_accounts", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.RMCLinkedAccount", b =>
|
||||
{
|
||||
b.Property<Guid>("PlayerId")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("player_id");
|
||||
|
||||
b.Property<ulong>("DiscordId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("discord_id");
|
||||
|
||||
b.HasKey("PlayerId")
|
||||
.HasName("PK_rmc_linked_accounts");
|
||||
|
||||
b.HasIndex("DiscordId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("rmc_linked_accounts", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.RMCLinkedAccountLogs", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("rmc_linked_accounts_logs_id");
|
||||
|
||||
b.Property<DateTime>("At")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("at");
|
||||
|
||||
b.Property<ulong>("DiscordId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("discord_id");
|
||||
|
||||
b.Property<Guid>("PlayerId")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("player_id");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_rmc_linked_accounts_logs");
|
||||
|
||||
b.HasIndex("At")
|
||||
.HasDatabaseName("IX_rmc_linked_accounts_logs_at");
|
||||
|
||||
b.HasIndex("DiscordId")
|
||||
.HasDatabaseName("IX_rmc_linked_accounts_logs_discord_id");
|
||||
|
||||
b.HasIndex("PlayerId")
|
||||
.HasDatabaseName("IX_rmc_linked_accounts_logs_player_id");
|
||||
|
||||
b.ToTable("rmc_linked_accounts_logs", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.RMCLinkingCodes", b =>
|
||||
{
|
||||
b.Property<Guid>("PlayerId")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("player_id");
|
||||
|
||||
b.Property<Guid>("Code")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("code");
|
||||
|
||||
b.Property<DateTime>("CreationTime")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("creation_time");
|
||||
|
||||
b.HasKey("PlayerId")
|
||||
.HasName("PK_rmc_linking_codes");
|
||||
|
||||
b.HasIndex("Code")
|
||||
.HasDatabaseName("IX_rmc_linking_codes_code");
|
||||
|
||||
b.ToTable("rmc_linking_codes", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.RMCPatron", b =>
|
||||
{
|
||||
b.Property<Guid>("PlayerId")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("player_id");
|
||||
|
||||
b.Property<int?>("GhostColor")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("ghost_color");
|
||||
|
||||
b.Property<int>("TierId")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("tier_id");
|
||||
|
||||
b.HasKey("PlayerId")
|
||||
.HasName("PK_rmc_patrons");
|
||||
|
||||
b.HasIndex("TierId")
|
||||
.HasDatabaseName("IX_rmc_patrons_tier_id");
|
||||
|
||||
b.ToTable("rmc_patrons", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.RMCPatronLobbyMessage", b =>
|
||||
{
|
||||
b.Property<Guid>("PatronId")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("patron_id");
|
||||
|
||||
b.Property<string>("Message")
|
||||
.IsRequired()
|
||||
.HasMaxLength(500)
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("message");
|
||||
|
||||
b.HasKey("PatronId")
|
||||
.HasName("PK_rmc_patron_lobby_messages");
|
||||
|
||||
b.ToTable("rmc_patron_lobby_messages", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.RMCPatronRoundEndNTShoutout", b =>
|
||||
{
|
||||
b.Property<Guid>("PatronId")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("patron_id");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("name");
|
||||
|
||||
b.HasKey("PatronId")
|
||||
.HasName("PK_rmc_patron_round_end_nt_shoutouts");
|
||||
|
||||
b.ToTable("rmc_patron_round_end_nt_shoutouts", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.RMCPatronTier", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("rmc_patron_tiers_id");
|
||||
|
||||
b.Property<ulong>("DiscordRole")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("discord_role");
|
||||
|
||||
b.Property<bool>("GhostColor")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("ghost_color");
|
||||
|
||||
b.Property<string>("Icon")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("icon");
|
||||
|
||||
b.Property<bool>("LobbyMessage")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("lobby_message");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("name");
|
||||
|
||||
b.Property<int>("Priority")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("priority");
|
||||
|
||||
b.Property<bool>("RoundEndShoutout")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("round_end_shoutout");
|
||||
|
||||
b.Property<bool>("ShowOnCredits")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("show_on_credits");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_rmc_patron_tiers");
|
||||
|
||||
b.HasIndex("DiscordRole")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("LobbyMessage")
|
||||
.HasDatabaseName("IX_rmc_patron_tiers_lobby_message");
|
||||
|
||||
b.HasIndex("RoundEndShoutout")
|
||||
.HasDatabaseName("IX_rmc_patron_tiers_round_end_shoutout");
|
||||
|
||||
b.ToTable("rmc_patron_tiers", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.RoleWhitelist", b =>
|
||||
{
|
||||
b.Property<Guid>("PlayerUserId")
|
||||
@@ -1735,6 +1938,109 @@ namespace Content.Server.Database.Migrations.Sqlite
|
||||
b.Navigation("Profile");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.RMCLinkedAccount", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.RMCDiscordAccount", "Discord")
|
||||
.WithOne("LinkedAccount")
|
||||
.HasForeignKey("Content.Server.Database.RMCLinkedAccount", "DiscordId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_rmc_linked_accounts_rmc_discord_accounts_discord_id");
|
||||
|
||||
b.HasOne("Content.Server.Database.Player", "Player")
|
||||
.WithOne("LinkedAccount")
|
||||
.HasForeignKey("Content.Server.Database.RMCLinkedAccount", "PlayerId")
|
||||
.HasPrincipalKey("Content.Server.Database.Player", "UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_rmc_linked_accounts_player_player_id");
|
||||
|
||||
b.Navigation("Discord");
|
||||
|
||||
b.Navigation("Player");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.RMCLinkedAccountLogs", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.RMCDiscordAccount", "Discord")
|
||||
.WithMany("LinkedAccountLogs")
|
||||
.HasForeignKey("DiscordId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_rmc_linked_accounts_logs_rmc_discord_accounts_discord_id");
|
||||
|
||||
b.HasOne("Content.Server.Database.Player", "Player")
|
||||
.WithMany("LinkedAccountLogs")
|
||||
.HasForeignKey("PlayerId")
|
||||
.HasPrincipalKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_rmc_linked_accounts_logs_player__player_id1");
|
||||
|
||||
b.Navigation("Discord");
|
||||
|
||||
b.Navigation("Player");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.RMCLinkingCodes", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Player", "Player")
|
||||
.WithOne("LinkingCodes")
|
||||
.HasForeignKey("Content.Server.Database.RMCLinkingCodes", "PlayerId")
|
||||
.HasPrincipalKey("Content.Server.Database.Player", "UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_rmc_linking_codes_player_player_id");
|
||||
|
||||
b.Navigation("Player");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.RMCPatron", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Player", "Player")
|
||||
.WithOne("Patron")
|
||||
.HasForeignKey("Content.Server.Database.RMCPatron", "PlayerId")
|
||||
.HasPrincipalKey("Content.Server.Database.Player", "UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_rmc_patrons_player_player_id");
|
||||
|
||||
b.HasOne("Content.Server.Database.RMCPatronTier", "Tier")
|
||||
.WithMany("Patrons")
|
||||
.HasForeignKey("TierId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_rmc_patrons_rmc_patron_tiers_tier_id");
|
||||
|
||||
b.Navigation("Player");
|
||||
|
||||
b.Navigation("Tier");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.RMCPatronLobbyMessage", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.RMCPatron", "Patron")
|
||||
.WithOne("LobbyMessage")
|
||||
.HasForeignKey("Content.Server.Database.RMCPatronLobbyMessage", "PatronId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_rmc_patron_lobby_messages_rmc_patrons_patron_id");
|
||||
|
||||
b.Navigation("Patron");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.RMCPatronRoundEndNTShoutout", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.RMCPatron", "Patron")
|
||||
.WithOne("RoundEndNTShoutout")
|
||||
.HasForeignKey("Content.Server.Database.RMCPatronRoundEndNTShoutout", "PatronId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("FK_rmc_patron_round_end_nt_shoutouts_rmc_patrons_patron_id");
|
||||
|
||||
b.Navigation("Patron");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.RoleWhitelist", b =>
|
||||
{
|
||||
b.HasOne("Content.Server.Database.Player", "Player")
|
||||
@@ -2005,6 +2311,14 @@ namespace Content.Server.Database.Migrations.Sqlite
|
||||
b.Navigation("AdminWatchlistsReceived");
|
||||
|
||||
b.Navigation("JobWhitelists");
|
||||
|
||||
b.Navigation("LinkedAccount");
|
||||
|
||||
b.Navigation("LinkedAccountLogs");
|
||||
|
||||
b.Navigation("LinkingCodes");
|
||||
|
||||
b.Navigation("Patron");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Preference", b =>
|
||||
@@ -2033,6 +2347,26 @@ namespace Content.Server.Database.Migrations.Sqlite
|
||||
b.Navigation("Groups");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.RMCDiscordAccount", b =>
|
||||
{
|
||||
b.Navigation("LinkedAccount")
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("LinkedAccountLogs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.RMCPatron", b =>
|
||||
{
|
||||
b.Navigation("LobbyMessage");
|
||||
|
||||
b.Navigation("RoundEndNTShoutout");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.RMCPatronTier", b =>
|
||||
{
|
||||
b.Navigation("Patrons");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Round", b =>
|
||||
{
|
||||
b.Navigation("AdminLogs");
|
||||
|
||||
@@ -47,6 +47,16 @@ namespace Content.Server.Database
|
||||
public DbSet<BanTemplate> BanTemplate { get; set; } = null!;
|
||||
public DbSet<IPIntelCache> IPIntelCache { get; set; } = null!;
|
||||
|
||||
// RMC14
|
||||
public DbSet<RMCDiscordAccount> RMCDiscordAccounts { get; set; } = default!;
|
||||
public DbSet<RMCLinkedAccount> RMCLinkedAccounts { get; set; } = default!;
|
||||
public DbSet<RMCPatronTier> RMCPatronTiers { get; set; } = default!;
|
||||
public DbSet<RMCPatron> RMCPatrons { get; set; } = default!;
|
||||
public DbSet<RMCLinkingCodes> RMCLinkingCodes { get; set; } = default!;
|
||||
public DbSet<RMCLinkedAccountLogs> RMCLinkedAccountLogs { get; set; } = default!;
|
||||
public DbSet<RMCPatronLobbyMessage> RMCPatronLobbyMessages { get; set; } = default!;
|
||||
public DbSet<RMCPatronRoundEndNTShoutout> RMCPatronRoundEndNTShoutouts { get; set; } = default!;
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder.Entity<Preference>()
|
||||
@@ -371,6 +381,60 @@ namespace Content.Server.Database
|
||||
.OwnsOne(p => p.HWId)
|
||||
.Property(p => p.Type)
|
||||
.HasDefaultValue(HwidType.Legacy);
|
||||
|
||||
// RMC14
|
||||
modelBuilder.Entity<RMCLinkedAccount>()
|
||||
.HasOne(l => l.Player)
|
||||
.WithOne(p => p.LinkedAccount)
|
||||
.HasForeignKey<RMCLinkedAccount>(l => l.PlayerId)
|
||||
.HasPrincipalKey<Player>(p => p.UserId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<RMCLinkedAccount>()
|
||||
.HasOne(l => l.Discord)
|
||||
.WithOne(d => d.LinkedAccount)
|
||||
.HasForeignKey<RMCLinkedAccount>(l => l.DiscordId)
|
||||
.HasPrincipalKey<RMCDiscordAccount>(d => d.Id)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<RMCPatron>()
|
||||
.HasOne(p => p.Player)
|
||||
.WithOne(p => p.Patron)
|
||||
.HasForeignKey<RMCPatron>(p => p.PlayerId)
|
||||
.HasPrincipalKey<Player>(p => p.UserId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<RMCPatron>()
|
||||
.HasOne(p => p.Tier)
|
||||
.WithMany(t => t.Patrons)
|
||||
.HasForeignKey(p => p.TierId)
|
||||
.HasPrincipalKey(p => p.Id)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<RMCPatronTier>()
|
||||
.HasIndex(t => t.DiscordRole)
|
||||
.IsUnique();
|
||||
|
||||
modelBuilder.Entity<RMCLinkingCodes>()
|
||||
.HasOne(l => l.Player)
|
||||
.WithOne(p => p.LinkingCodes)
|
||||
.HasForeignKey<RMCLinkingCodes>(l => l.PlayerId)
|
||||
.HasPrincipalKey<Player>(p => p.UserId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<RMCLinkedAccountLogs>()
|
||||
.HasOne(l => l.Player)
|
||||
.WithMany(p => p.LinkedAccountLogs)
|
||||
.HasForeignKey(l => l.PlayerId)
|
||||
.HasPrincipalKey(p => p.UserId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<RMCLinkedAccountLogs>()
|
||||
.HasOne(l => l.Discord)
|
||||
.WithMany(p => p.LinkedAccountLogs)
|
||||
.HasForeignKey(l => l.DiscordId)
|
||||
.HasPrincipalKey(p => p.Id)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
}
|
||||
|
||||
public virtual IQueryable<AdminLog> SearchLogs(IQueryable<AdminLog> query, string searchText)
|
||||
@@ -600,6 +664,12 @@ namespace Content.Server.Database
|
||||
public List<ServerRoleBan> AdminServerRoleBansCreated { get; set; } = null!;
|
||||
public List<ServerRoleBan> AdminServerRoleBansLastEdited { get; set; } = null!;
|
||||
public List<RoleWhitelist> JobWhitelists { get; set; } = null!;
|
||||
|
||||
// RMC14
|
||||
public RMCLinkedAccount? LinkedAccount { get; set; }
|
||||
public RMCPatron? Patron { get; set; }
|
||||
public RMCLinkingCodes? LinkingCodes { get; set; }
|
||||
public List<RMCLinkedAccountLogs> LinkedAccountLogs { get; set; } = default!;
|
||||
}
|
||||
|
||||
[Table("whitelist")]
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Content.Server.Database;
|
||||
|
||||
[Table("rmc_discord_accounts")]
|
||||
public sealed class RMCDiscordAccount
|
||||
{
|
||||
[Key]
|
||||
public ulong Id { get; set; }
|
||||
|
||||
public RMCLinkedAccount LinkedAccount { get; set; } = default!;
|
||||
public List<RMCLinkedAccountLogs> LinkedAccountLogs { get; set; } = default!;
|
||||
}
|
||||
|
||||
[Table("rmc_linked_accounts")]
|
||||
public sealed class RMCLinkedAccount
|
||||
{
|
||||
[Key]
|
||||
public Guid PlayerId { get; set; }
|
||||
|
||||
public Player Player { get; set; } = default!;
|
||||
|
||||
public ulong DiscordId { get; set; }
|
||||
|
||||
public RMCDiscordAccount Discord { get; set; } = default!;
|
||||
}
|
||||
|
||||
[Table("rmc_patron_tiers")]
|
||||
[Index(nameof(LobbyMessage))]
|
||||
[Index(nameof(RoundEndShoutout))]
|
||||
public sealed class RMCPatronTier
|
||||
{
|
||||
[Key]
|
||||
public int Id { get; set; }
|
||||
|
||||
public bool ShowOnCredits { get; set; }
|
||||
|
||||
public bool GhostColor { get; set; }
|
||||
|
||||
public bool LobbyMessage { get; set; }
|
||||
|
||||
public bool RoundEndShoutout { get; set; }
|
||||
|
||||
public string Name { get; set; } = default!;
|
||||
|
||||
public string? Icon { get; set; }
|
||||
|
||||
public ulong DiscordRole { get; set; }
|
||||
|
||||
public int Priority { get; set; }
|
||||
|
||||
public List<RMCPatron> Patrons { get; set; } = default!;
|
||||
}
|
||||
|
||||
[Table("rmc_patrons")]
|
||||
[Index(nameof(TierId))]
|
||||
public sealed class RMCPatron
|
||||
{
|
||||
[Key]
|
||||
public Guid PlayerId { get; set; }
|
||||
|
||||
public Player Player { get; set; } = default!;
|
||||
|
||||
public int TierId { get; set; }
|
||||
|
||||
public RMCPatronTier Tier { get; set; } = default!;
|
||||
public int? GhostColor { get; set; } = default!;
|
||||
public RMCPatronLobbyMessage? LobbyMessage { get; set; } = default!;
|
||||
public RMCPatronRoundEndNTShoutout? RoundEndNTShoutout { get; set; } = default!;
|
||||
}
|
||||
|
||||
[Table("rmc_linking_codes")]
|
||||
[Index(nameof(Code))]
|
||||
public sealed class RMCLinkingCodes
|
||||
{
|
||||
[Key]
|
||||
public Guid PlayerId { get; set; }
|
||||
|
||||
public Player Player { get; set; } = default!;
|
||||
|
||||
public Guid Code { get; set; }
|
||||
|
||||
public DateTime CreationTime { get; set; }
|
||||
}
|
||||
|
||||
[Table("rmc_linked_accounts_logs")]
|
||||
[Index(nameof(PlayerId))]
|
||||
[Index(nameof(DiscordId))]
|
||||
[Index(nameof(At))]
|
||||
public sealed class RMCLinkedAccountLogs
|
||||
{
|
||||
[Key]
|
||||
public int Id { get; set; }
|
||||
|
||||
public Guid PlayerId { get; set; }
|
||||
|
||||
public Player Player { get; set; } = default!;
|
||||
|
||||
public ulong DiscordId { get; set; }
|
||||
|
||||
public RMCDiscordAccount Discord { get; set; } = default!;
|
||||
|
||||
public DateTime At { get; set; }
|
||||
}
|
||||
|
||||
[Table(("rmc_patron_lobby_messages"))]
|
||||
public sealed class RMCPatronLobbyMessage
|
||||
{
|
||||
[Key, ForeignKey("Patron")]
|
||||
public Guid PatronId { get; set; }
|
||||
|
||||
public RMCPatron Patron { get; set; } = default!;
|
||||
|
||||
[StringLength(500)]
|
||||
public string Message { get; set; } = default!;
|
||||
}
|
||||
|
||||
[Table(("rmc_patron_round_end_nt_shoutouts"))]
|
||||
public sealed class RMCPatronRoundEndNTShoutout
|
||||
{
|
||||
[Key, ForeignKey("Patron")]
|
||||
public Guid PatronId { get; set; }
|
||||
|
||||
public RMCPatron Patron { get; set; } = default!;
|
||||
|
||||
[StringLength(100), Required]
|
||||
public string Name { get; set; } = default!;
|
||||
}
|
||||
@@ -392,7 +392,8 @@ namespace Content.Server.Administration.Managers
|
||||
|
||||
_admins.Add(session, reg);
|
||||
|
||||
if (session.ContentData()!.Stealthed)
|
||||
var contentData = session.ContentData(); // Goobstation - Queue
|
||||
if (contentData != null && contentData.Stealthed)
|
||||
reg.Data.Stealth = true;
|
||||
|
||||
if (reg.Data.Active)
|
||||
|
||||
@@ -20,6 +20,7 @@ using Robust.Shared.Network;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Replays;
|
||||
using Robust.Shared.Utility;
|
||||
using Content.Server._RMC14.LinkAccount; // RMC - Patreon
|
||||
|
||||
namespace Content.Server.Chat.Managers;
|
||||
|
||||
@@ -45,6 +46,7 @@ internal sealed partial class ChatManager : IChatManager
|
||||
[Dependency] private readonly INetConfigurationManager _netConfigManager = default!;
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
[Dependency] private readonly PlayerRateLimitManager _rateLimitManager = default!;
|
||||
[Dependency] private readonly LinkAccountManager _linkAccount = default!; // RMC - Patreon
|
||||
[Dependency] private readonly ISharedPlayerManager _player = default!;
|
||||
[Dependency] private readonly DiscordChatLink _discordLink = default!;
|
||||
|
||||
@@ -298,12 +300,25 @@ internal sealed partial class ChatManager : IChatManager
|
||||
var prefs = _preferencesManager.GetPreferences(player.UserId);
|
||||
colorOverride = prefs.AdminOOCColor;
|
||||
}
|
||||
// RMC - Heavily modified for patreon.
|
||||
if (_netConfigManager.GetClientCVar(player.Channel, CCVars.ShowOocPatronColor) &&
|
||||
player.Channel.UserData.PatronTier is { } patron &&
|
||||
PatronOocColors.TryGetValue(patron, out var patronColor) &&
|
||||
!string.IsNullOrEmpty(patronColor))
|
||||
_linkAccount.GetPatron(player)?.Tier is { } tier)
|
||||
{
|
||||
wrappedMessage = Loc.GetString("chat-manager-send-ooc-patron-wrap-message", ("patronColor", patronColor),("playerName", player.Name), ("message", FormattedMessage.EscapeText(message)));
|
||||
if (tier.Icon != null)
|
||||
{
|
||||
wrappedMessage = Loc.GetString("chat-manager-send-ooc-patron-wrap-message",
|
||||
("tierIcon", tier.Icon),
|
||||
("patronColor", "#aa00ff"),
|
||||
("playerName", player.Name),
|
||||
("message", FormattedMessage.EscapeText(message)));
|
||||
}
|
||||
else
|
||||
{
|
||||
wrappedMessage = Loc.GetString("chat-manager-send-ooc-patron-wrap-message-no-icon",
|
||||
("patronColor", "#aa00ff"),
|
||||
("playerName", player.Name),
|
||||
("message", FormattedMessage.EscapeText(message)));
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: player.Name color, this will need to change the structure of the MsgChatMessage
|
||||
|
||||
@@ -19,6 +19,7 @@ using Robust.Shared.Network;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Timing;
|
||||
using Content.Shared._Goobstation.CCVars; // Goobstation - Queue
|
||||
using Content.Server._NF.Auth; // Frontier
|
||||
|
||||
/*
|
||||
@@ -31,7 +32,7 @@ namespace Content.Server.Connection
|
||||
{
|
||||
void Initialize();
|
||||
void PostInit();
|
||||
|
||||
Task<bool> HasPrivilegedJoin(NetUserId userId); // Goobstation - Queue
|
||||
/// <summary>
|
||||
/// Temporarily allow a user to bypass regular connection requirements.
|
||||
/// </summary>
|
||||
@@ -307,6 +308,8 @@ namespace Content.Server.Connection
|
||||
}
|
||||
}
|
||||
|
||||
var isPrivileged = await HasPrivilegedJoin(userId); // Goobstation - Queue
|
||||
var isQueueEnabled = _cfg.GetCVar(GoobCVars.QueueEnabled); // Goobstation - Queue
|
||||
// Frontier: wasInGame previously calculated here.
|
||||
var adminBypass = _cfg.GetCVar(CCVars.AdminBypassMaxPlayers) && adminData != null;
|
||||
var softPlayerCount = _plyMgr.PlayerCount;
|
||||
@@ -316,7 +319,7 @@ namespace Content.Server.Connection
|
||||
softPlayerCount -= _adminManager.ActiveAdmins.Count();
|
||||
}
|
||||
|
||||
if ((softPlayerCount >= _cfg.GetCVar(CCVars.SoftMaxPlayers) && !adminBypass) && !wasInGame)
|
||||
if (softPlayerCount >= _cfg.GetCVar(CCVars.SoftMaxPlayers) && !isPrivileged && !isQueueEnabled) // Goobstation - Queue
|
||||
{
|
||||
return (ConnectionDenyReason.Full, Loc.GetString("soft-player-cap-full"), null);
|
||||
}
|
||||
@@ -401,5 +404,14 @@ namespace Content.Server.Connection
|
||||
await _db.AssignUserIdAsync(name, assigned);
|
||||
return assigned;
|
||||
}
|
||||
|
||||
public async Task<bool> HasPrivilegedJoin(NetUserId userId) // Goobstation - Queue
|
||||
{
|
||||
var isAdmin = await _db.GetAdminDataForAsync(userId) != null;
|
||||
var ticker = IoCManager.Resolve<IEntityManager>().System<GameTicker>();
|
||||
var wasInGame = ticker.PlayerGameStatuses.TryGetValue(userId, out var status) &&
|
||||
status == PlayerGameStatus.JoinedGame;
|
||||
return isAdmin || wasInGame;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.Administration.Logs;
|
||||
using Content.Server.Administration.Managers;
|
||||
using Content.Shared._RMC14.LinkAccount;
|
||||
using Content.Shared.Administration.Logs;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.Ghost.Roles;
|
||||
@@ -1819,6 +1820,134 @@ INSERT INTO player_round (players_id, rounds_id) VALUES ({players[player]}, {id}
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region RMC14
|
||||
|
||||
public async Task<Guid?> GetLinkingCode(Guid player)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
var linking = await db.DbContext.RMCLinkingCodes.FirstOrDefaultAsync(l => l.PlayerId == player);
|
||||
return linking?.Code;
|
||||
}
|
||||
|
||||
public async Task SetLinkingCode(Guid player, Guid code)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
var linking = await db.DbContext.RMCLinkingCodes.FirstOrDefaultAsync(l => l.PlayerId == player);
|
||||
if (linking == null)
|
||||
{
|
||||
linking = new RMCLinkingCodes { PlayerId = player };
|
||||
db.DbContext.RMCLinkingCodes.Add(linking);
|
||||
}
|
||||
|
||||
linking.Code = code;
|
||||
linking.CreationTime = DateTime.UtcNow;
|
||||
await db.DbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task<bool> HasLinkedAccount(Guid player, CancellationToken cancel)
|
||||
{
|
||||
await using var db = await GetDb(cancel);
|
||||
return await db.DbContext.RMCLinkedAccounts.AnyAsync(l => l.PlayerId == player, cancel);
|
||||
|
||||
}
|
||||
|
||||
public async Task<RMCPatron?> GetPatron(Guid player, CancellationToken cancel)
|
||||
{
|
||||
await using var db = await GetDb(cancel);
|
||||
var patron = await db.DbContext.RMCPatrons
|
||||
.Include(p => p.Tier)
|
||||
.Include(p => p.LobbyMessage)
|
||||
.Include(p => p.RoundEndNTShoutout)
|
||||
.FirstOrDefaultAsync(p => p.PlayerId == player, cancellationToken: cancel);
|
||||
return patron;
|
||||
}
|
||||
|
||||
public async Task<List<RMCPatron>> GetAllPatrons()
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
return await db.DbContext.RMCPatrons
|
||||
.Include(p => p.Player)
|
||||
.Include(p => p.Tier)
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
public async Task SetGhostColor(Guid player, System.Drawing.Color? color)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
var patron = await db.DbContext.RMCPatrons.FirstOrDefaultAsync(p => p.PlayerId == player);
|
||||
if (patron == null)
|
||||
return;
|
||||
|
||||
patron.GhostColor = color?.ToArgb();
|
||||
await db.DbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task SetLobbyMessage(Guid player, string message)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
var msg = await db.DbContext.RMCPatronLobbyMessages
|
||||
.Include(l => l.Patron)
|
||||
.FirstOrDefaultAsync(p => p.PatronId == player);
|
||||
msg ??= db.DbContext.RMCPatronLobbyMessages
|
||||
.Add(new RMCPatronLobbyMessage
|
||||
{
|
||||
PatronId = player,
|
||||
Message = message,
|
||||
})
|
||||
.Entity;
|
||||
msg.Message = message;
|
||||
|
||||
await db.DbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task SetNTShoutout(Guid player, string name)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
var msg = await db.DbContext.RMCPatronRoundEndNTShoutouts
|
||||
.Include(s => s.Patron)
|
||||
.FirstOrDefaultAsync(p => p.PatronId == player);
|
||||
msg ??= db.DbContext.RMCPatronRoundEndNTShoutouts
|
||||
.Add(new RMCPatronRoundEndNTShoutout()
|
||||
{
|
||||
PatronId = player,
|
||||
Name = name,
|
||||
})
|
||||
.Entity;
|
||||
msg.Name = name;
|
||||
|
||||
await db.DbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task<List<(string Message, string User)>> GetLobbyMessages()
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
var messages = await db.DbContext.RMCPatronLobbyMessages
|
||||
.Include(p => p.Patron)
|
||||
.ThenInclude(p => p.Player)
|
||||
.Where(p => p.Patron.Tier.LobbyMessage)
|
||||
.Where(p => !string.IsNullOrWhiteSpace(p.Message))
|
||||
.Select(p => new { p.Message, p.Patron.Player.LastSeenUserName })
|
||||
.Select(p => new ValueTuple<string, string>(p.Message, p.LastSeenUserName))
|
||||
.ToListAsync();
|
||||
|
||||
return messages;
|
||||
}
|
||||
|
||||
public async Task<List<string>> GetShoutouts()
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
var ntNames = await db.DbContext.RMCPatronRoundEndNTShoutouts
|
||||
.Include(p => p.Patron)
|
||||
.Where(p => p.Patron.Tier.RoundEndShoutout)
|
||||
.Where(p => !string.IsNullOrWhiteSpace(p.Name))
|
||||
.Select(p => p.Name)
|
||||
.ToListAsync();
|
||||
|
||||
return ntNames;
|
||||
}
|
||||
|
||||
// Frontier: Ghost role handling
|
||||
# endregion
|
||||
|
||||
|
||||
@@ -351,6 +351,30 @@ namespace Content.Server.Database
|
||||
|
||||
#endregion
|
||||
|
||||
#region RMC14
|
||||
|
||||
Task<Guid?> GetLinkingCode(Guid player);
|
||||
|
||||
Task SetLinkingCode(Guid player, Guid code);
|
||||
|
||||
Task<bool> HasLinkedAccount(Guid player, CancellationToken cancel);
|
||||
|
||||
Task<RMCPatron?> GetPatron(Guid player, CancellationToken cancel);
|
||||
|
||||
Task<List<RMCPatron>> GetAllPatrons();
|
||||
|
||||
Task SetGhostColor(Guid player, System.Drawing.Color? color);
|
||||
|
||||
Task SetLobbyMessage(Guid player, string message);
|
||||
|
||||
Task SetNTShoutout(Guid player, string name);
|
||||
|
||||
Task<List<(string, string)>> GetLobbyMessages();
|
||||
|
||||
Task<List<string>> GetShoutouts();
|
||||
|
||||
#endregion
|
||||
|
||||
#region DB Notifications
|
||||
|
||||
void SubscribeToNotifications(Action<DatabaseNotification> handler);
|
||||
@@ -1095,6 +1119,70 @@ namespace Content.Server.Database
|
||||
return RunDbCommand(() => _db.CleanIPIntelCache(range));
|
||||
}
|
||||
|
||||
#region RMC
|
||||
|
||||
public Task<Guid?> GetLinkingCode(Guid player)
|
||||
{
|
||||
DbReadOpsMetric.Inc();
|
||||
return RunDbCommand(() => _db.GetLinkingCode(player));
|
||||
}
|
||||
|
||||
public Task SetLinkingCode(Guid player, Guid code)
|
||||
{
|
||||
DbWriteOpsMetric.Inc();
|
||||
return RunDbCommand(() => _db.SetLinkingCode(player, code));
|
||||
}
|
||||
|
||||
public Task<bool> HasLinkedAccount(Guid player, CancellationToken cancel)
|
||||
{
|
||||
DbReadOpsMetric.Inc();
|
||||
return RunDbCommand(() => _db.HasLinkedAccount(player, cancel));
|
||||
}
|
||||
|
||||
public Task<RMCPatron?> GetPatron(Guid player, CancellationToken cancel)
|
||||
{
|
||||
DbReadOpsMetric.Inc();
|
||||
return RunDbCommand(() => _db.GetPatron(player, cancel));
|
||||
}
|
||||
|
||||
public Task<List<RMCPatron>> GetAllPatrons()
|
||||
{
|
||||
DbReadOpsMetric.Inc();
|
||||
return RunDbCommand(() => _db.GetAllPatrons());
|
||||
}
|
||||
|
||||
public Task SetGhostColor(Guid player, System.Drawing.Color? color)
|
||||
{
|
||||
DbWriteOpsMetric.Inc();
|
||||
return RunDbCommand(() => _db.SetGhostColor(player, color));
|
||||
}
|
||||
|
||||
public Task SetLobbyMessage(Guid player, string message)
|
||||
{
|
||||
DbWriteOpsMetric.Inc();
|
||||
return RunDbCommand(() => _db.SetLobbyMessage(player, message));
|
||||
}
|
||||
|
||||
public Task SetNTShoutout(Guid player, string name)
|
||||
{
|
||||
DbWriteOpsMetric.Inc();
|
||||
return RunDbCommand(() => _db.SetNTShoutout(player, name));
|
||||
}
|
||||
|
||||
public Task<List<(string, string)>> GetLobbyMessages()
|
||||
{
|
||||
DbReadOpsMetric.Inc();
|
||||
return RunDbCommand(() => _db.GetLobbyMessages());
|
||||
}
|
||||
|
||||
public Task<List<string>> GetShoutouts()
|
||||
{
|
||||
DbReadOpsMetric.Inc();
|
||||
return RunDbCommand(() => _db.GetShoutouts());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public void SubscribeToNotifications(Action<DatabaseNotification> handler)
|
||||
{
|
||||
lock (_notificationHandlers)
|
||||
|
||||
@@ -57,10 +57,6 @@ namespace Content.Server.GameTicking
|
||||
session.Data.ContentDataUncast = data;
|
||||
}
|
||||
|
||||
// Make the player actually join the game.
|
||||
// timer time must be > tick length
|
||||
Timer.Spawn(0, () => _playerManager.JoinGame(args.Session));
|
||||
|
||||
var record = await _db.GetPlayerRecordByUserId(args.Session.UserId);
|
||||
var firstConnection = record != null &&
|
||||
Math.Abs((record.FirstSeenTime - record.LastSeenTime).TotalMinutes) < 1;
|
||||
@@ -134,7 +130,8 @@ namespace Content.Server.GameTicking
|
||||
mind.Session = null;
|
||||
}
|
||||
|
||||
_userDb.ClientDisconnected(session);
|
||||
if (_playerGameStatuses.ContainsKey(session.UserId)) // Goobstation - Queue
|
||||
_userDb.ClientDisconnected(session);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ using Content.Shared.CCVar;
|
||||
using Content.Shared.GameTicking;
|
||||
using Robust.Server.ServerStatus;
|
||||
using Robust.Shared.Configuration;
|
||||
using Content.Shared._Goobstation.JoinQueue; // Goobstation - Queue
|
||||
|
||||
namespace Content.Server.GameTicking
|
||||
{
|
||||
@@ -28,6 +29,7 @@ namespace Content.Server.GameTicking
|
||||
/// For access to the round ID in status responses.
|
||||
/// </summary>
|
||||
[Dependency] private readonly SharedGameTicker _gameTicker = default!;
|
||||
[Dependency] private readonly IJoinQueueManager _joinQueue = default!; // Goobstation - Queue
|
||||
|
||||
private void InitializeStatusShell()
|
||||
{
|
||||
@@ -44,9 +46,7 @@ namespace Content.Server.GameTicking
|
||||
jObject["name"] = _baseServer.ServerName;
|
||||
jObject["map"] = _gameMapManager.GetSelectedMap()?.MapName;
|
||||
jObject["round_id"] = _gameTicker.RoundId;
|
||||
jObject["players"] = _cfg.GetCVar(CCVars.AdminsCountInReportedPlayerCount)
|
||||
? _playerManager.PlayerCount
|
||||
: _playerManager.PlayerCount - _adminManager.ActiveAdmins.Count();
|
||||
jObject["players"] = _joinQueue.ActualPlayersCount; // Goobstation - Queue
|
||||
jObject["soft_max_players"] = _cfg.GetCVar(CCVars.SoftMaxPlayers);
|
||||
jObject["panic_bunker"] = _cfg.GetCVar(CCVars.PanicBunkerEnabled);
|
||||
jObject["run_level"] = (int) _runLevel;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Content.Server._RMC14.LinkAccount; // RMC - Patreon
|
||||
using Content.Server._NF.Auth;
|
||||
using Content.Server.Administration;
|
||||
using Content.Server.Administration.Logs;
|
||||
@@ -73,6 +74,7 @@ namespace Content.Server.IoC
|
||||
IoCManager.Register<PlayerRateLimitManager>();
|
||||
IoCManager.Register<SharedPlayerRateLimitManager, PlayerRateLimitManager>();
|
||||
IoCManager.Register<MappingManager>();
|
||||
IoCManager.Register<LinkAccountManager>(); // RMC - Patreon
|
||||
IoCManager.Register<IWatchlistWebhookManager, WatchlistWebhookManager>();
|
||||
IoCManager.Register<ConnectionManager>();
|
||||
IoCManager.Register<MultiServerKickManager>();
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
using Content.Server._RMC14.LinkAccount;
|
||||
using Content.Server.Administration;
|
||||
using Content.Shared._RMC14.LinkAccount;
|
||||
using Content.Shared.Administration;
|
||||
using Robust.Shared.Console;
|
||||
|
||||
namespace Content.Server._Goobstation.Administration.Commands;
|
||||
|
||||
[AdminCommand(AdminFlags.Host)]
|
||||
internal sealed class AddPatronTierCommand : LocalizedCommands
|
||||
{
|
||||
private static readonly string[] BoolOptions = ["true", "false"];
|
||||
|
||||
[Dependency] private readonly LinkAccountManager _linkAccount = default!;
|
||||
|
||||
public override string Command => "addpatrontier";
|
||||
|
||||
public override string Description => "Create a debug patron tier for testing";
|
||||
|
||||
public override string Help => "Usage: addpatrontier <tierId> <tierName> <icon?> <credits?> <ghostcolor?> <lobbymessage?> <shoutout?>\n" +
|
||||
"Example: addpatrontier captain Captain JobIconCaptain true true true true";
|
||||
|
||||
public override void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length < 2)
|
||||
{
|
||||
shell.WriteError("Usage: addpatrontier <tierId> <tierName> <icon?> <credits?> <ghostcolor?> <lobbymessage?> <shoutout?>");
|
||||
shell.WriteError("Example: addpatrontier captain \"Captain\" JobIconCaptain true true true true");
|
||||
return;
|
||||
}
|
||||
|
||||
var tierId = args[0];
|
||||
var tierName = args[1];
|
||||
var icon = args.Length > 2 && !string.IsNullOrEmpty(args[2]) ? args[2] : null;
|
||||
var showOnCredits = args.Length > 3 && bool.TryParse(args[3], out var credits) && credits;
|
||||
var ghostColor = args.Length > 4 && bool.TryParse(args[4], out var ghost) && ghost;
|
||||
var lobbyMessage = args.Length > 5 && bool.TryParse(args[5], out var lobby) && lobby;
|
||||
var roundEndShoutout = args.Length > 6 && bool.TryParse(args[6], out var shoutout) && shoutout;
|
||||
|
||||
var tier = new SharedRMCPatronTier(
|
||||
ShowOnCredits: showOnCredits,
|
||||
GhostColor: ghostColor,
|
||||
LobbyMessage: lobbyMessage,
|
||||
RoundEndShoutout: roundEndShoutout,
|
||||
Tier: tierName,
|
||||
Icon: icon
|
||||
);
|
||||
|
||||
_linkAccount.AddFauxTier(tierId, tier);
|
||||
|
||||
shell.WriteLine($"Faux patron tier '{tierId}' created:");
|
||||
shell.WriteLine($" Name: {tierName}");
|
||||
shell.WriteLine($" Icon: {icon ?? "None"}");
|
||||
shell.WriteLine($" Credits: {showOnCredits}");
|
||||
shell.WriteLine($" Ghost Color: {ghostColor}");
|
||||
shell.WriteLine($" Lobby Message: {lobbyMessage}");
|
||||
shell.WriteLine($" Shoutout: {roundEndShoutout}");
|
||||
}
|
||||
|
||||
public override CompletionResult GetCompletion(IConsoleShell shell, string[] args)
|
||||
{
|
||||
return args.Length switch
|
||||
{
|
||||
1 => CompletionResult.FromHint("<tierId>"),
|
||||
2 => CompletionResult.FromHint("<tierName>"),
|
||||
3 => CompletionResult.FromHint("<icon?>"),
|
||||
4 => CompletionResult.FromHintOptions(BoolOptions, "<credits?>"),
|
||||
5 => CompletionResult.FromHintOptions(BoolOptions, "<ghostcolor?>"),
|
||||
6 => CompletionResult.FromHintOptions(BoolOptions, "<lobbymessage?>"),
|
||||
7 => CompletionResult.FromHintOptions(BoolOptions, "<shoutout?>"),
|
||||
_ => CompletionResult.Empty
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
using System.Linq;
|
||||
using Content.Server._RMC14.LinkAccount;
|
||||
using Content.Server.Administration;
|
||||
using Content.Shared.Administration;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.Player;
|
||||
|
||||
namespace Content.Server._Goobstation.Administration.Commands;
|
||||
|
||||
[AdminCommand(AdminFlags.Host)]
|
||||
internal sealed class ListPatronTiersCommand : LocalizedCommands
|
||||
{
|
||||
[Dependency] private readonly LinkAccountManager _linkAccount = default!;
|
||||
[Dependency] private readonly ISharedPlayerManager _playerManager = default!;
|
||||
|
||||
public override string Command => "listpatrontiers";
|
||||
|
||||
public override string Description => "List all debug patron tiers and their assignments";
|
||||
|
||||
public override string Help => "Usage: listpatrontiers\n" +
|
||||
"Shows all defined patron tiers and which players have them assigned.";
|
||||
|
||||
public override void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var tiers = _linkAccount.GetAllFauxTiers();
|
||||
var assignments = _linkAccount.GetAllFauxPatronAssignments();
|
||||
|
||||
if (tiers.Count == 0)
|
||||
{
|
||||
shell.WriteLine("No faux patron tiers defined.");
|
||||
shell.WriteLine("Use 'addpatrontier' to create one.");
|
||||
return;
|
||||
}
|
||||
|
||||
shell.WriteLine($"Active Debug Patrons ({tiers.Count}):");
|
||||
shell.WriteLine("=====================================");
|
||||
|
||||
foreach (var (tierId, tier) in tiers)
|
||||
{
|
||||
shell.WriteLine($"[{tierId}] {tier.Tier}");
|
||||
shell.WriteLine($" Icon: {tier.Icon ?? "None"}");
|
||||
shell.WriteLine($" Credits: {tier.ShowOnCredits} | Ghost Color: {tier.GhostColor}");
|
||||
shell.WriteLine($" Lobby Message: {tier.LobbyMessage} | Shoutout: {tier.RoundEndShoutout}");
|
||||
|
||||
var assignedUsers = assignments.Where(kvp => kvp.Value == tierId).ToList();
|
||||
if (assignedUsers.Count > 0)
|
||||
{
|
||||
shell.WriteLine(" Assigned to:");
|
||||
foreach (var (userId, _) in assignedUsers)
|
||||
{
|
||||
var playerName = "Unknown";
|
||||
if (_playerManager.TryGetSessionById(userId, out var session))
|
||||
{
|
||||
playerName = session.Name;
|
||||
}
|
||||
shell.WriteLine($" - {playerName}");
|
||||
}
|
||||
}
|
||||
shell.WriteLine("");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
using System.Linq;
|
||||
using Content.Server._RMC14.LinkAccount;
|
||||
using Content.Server.Administration;
|
||||
using Content.Shared.Administration;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.Player;
|
||||
|
||||
namespace Content.Server._Goobstation.Administration.Commands;
|
||||
|
||||
[AdminCommand(AdminFlags.Host)]
|
||||
internal sealed class SetPatronCommand : LocalizedCommands
|
||||
{
|
||||
[Dependency] private readonly LinkAccountManager _linkAccount = default!;
|
||||
[Dependency] private readonly ISharedPlayerManager _playerManager = default!;
|
||||
|
||||
public override string Command => "setpatron";
|
||||
|
||||
public override string Description => "Assign a debug patron tier to a player";
|
||||
|
||||
public override string Help => "Usage: setpatron <player> <tierId|clear>\n" +
|
||||
"Example: setpatron \"John Doe\" captain\n" +
|
||||
"Example: setpatron username clear";
|
||||
|
||||
public override void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length < 2)
|
||||
{
|
||||
shell.WriteError("Usage: setpatron <player> <tierId|clear>");
|
||||
shell.WriteError("Example: setpatron \"John Doe\" captain");
|
||||
shell.WriteError("Example: setpatron username clear");
|
||||
return;
|
||||
}
|
||||
|
||||
var targetName = args[0];
|
||||
var tierId = args[1];
|
||||
|
||||
ICommonSession? targetSession = null;
|
||||
foreach (var session in _playerManager.Sessions)
|
||||
{
|
||||
if (session.Name.Equals(targetName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
targetSession = session;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (targetSession == null)
|
||||
{
|
||||
shell.WriteError($"Player '{targetName}' not found.");
|
||||
return;
|
||||
}
|
||||
|
||||
var userId = targetSession.UserId;
|
||||
|
||||
if (tierId.Equals("clear", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
_linkAccount.AssignFauxPatron(userId, null);
|
||||
shell.WriteLine($"Faux patron cleared for {targetSession.Name}.");
|
||||
return;
|
||||
}
|
||||
|
||||
var tiers = _linkAccount.GetAllFauxTiers();
|
||||
if (!tiers.ContainsKey(tierId))
|
||||
{
|
||||
shell.WriteError($"Tier '{tierId}' not found. Use 'listpatrontiers' to see available tiers.");
|
||||
return;
|
||||
}
|
||||
|
||||
_linkAccount.AssignFauxPatron(userId, tierId);
|
||||
shell.WriteLine($"Faux patron tier '{tierId}' assigned to {targetSession.Name}.");
|
||||
}
|
||||
|
||||
public override CompletionResult GetCompletion(IConsoleShell shell, string[] args)
|
||||
{
|
||||
if (args.Length == 1)
|
||||
{
|
||||
var playerNames = _playerManager.Sessions.Select(s => s.Name);
|
||||
return CompletionResult.FromHintOptions(playerNames, "<player>");
|
||||
}
|
||||
|
||||
if (args.Length == 2)
|
||||
{
|
||||
var tiers = _linkAccount.GetAllFauxTiers();
|
||||
var options = tiers.Keys.Append("clear");
|
||||
return CompletionResult.FromHintOptions(options, "<tierId|clear>");
|
||||
}
|
||||
|
||||
return CompletionResult.Empty;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com>
|
||||
// SPDX-FileCopyrightText: 2025 Misandry <mary@thughunt.ing>
|
||||
// SPDX-FileCopyrightText: 2025 gus <august.eymann@gmail.com>
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
using Content.Server.IoC;
|
||||
using Content.Shared._Goobstation.JoinQueue;
|
||||
using Robust.Shared.ContentPack;
|
||||
using Robust.Shared.IoC;
|
||||
|
||||
namespace Content.Server._Goobstation.Entry;
|
||||
|
||||
public sealed class EntryPoint : GameServer
|
||||
{
|
||||
public override void Init()
|
||||
{
|
||||
base.Init();
|
||||
|
||||
ServerContentIoC.Register();
|
||||
|
||||
IoCManager.BuildGraph();
|
||||
|
||||
IoCManager.Resolve<IJoinQueueManager>().Initialize();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
// using Content.Goobstation.Server.Explosion.Components;
|
||||
// using Content.Goobstation.Server.Explosion.Components.OnTrigger;
|
||||
// using Content.Server._Goobstation.Explosion.Components;
|
||||
// using Content.Server._Goobstation.Explosion.Components.OnTrigger;
|
||||
using Content.Server._Goobstation.Explosion.Components;
|
||||
// using Content.Server.Explosion.Components;
|
||||
using Content.Server.Explosion.EntitySystems;
|
||||
|
||||
@@ -0,0 +1,222 @@
|
||||
// SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com>
|
||||
// SPDX-FileCopyrightText: 2025 GoobBot <uristmchands@proton.me>
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
using System.Linq;
|
||||
using Content.Server.Connection;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared._Goobstation.JoinQueue;
|
||||
using Prometheus;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Timing;
|
||||
using Content.Shared._Goobstation.CCVars;
|
||||
using Content.Server._RMC14.LinkAccount;
|
||||
using Content.Server.IoC;
|
||||
|
||||
namespace Content.Server._Goobstation.JoinQueue;
|
||||
|
||||
/// <summary>
|
||||
/// Manages new player connections when the server is full and queues them up, granting access when a slot becomes free
|
||||
/// </summary>
|
||||
public sealed class JoinQueueManager : IJoinQueueManager
|
||||
{
|
||||
private static readonly Gauge QueueCount = Metrics.CreateGauge(
|
||||
"join_queue_total_count",
|
||||
"Amount of players in queue.");
|
||||
|
||||
private static readonly Counter QueueBypassCount = Metrics.CreateCounter(
|
||||
"join_queue_bypass_count",
|
||||
"Amount of players who bypassed queue by privileges.");
|
||||
|
||||
private static readonly Histogram QueueTimings = Metrics.CreateHistogram(
|
||||
"join_queue_timings",
|
||||
"Timings of players in queue",
|
||||
new HistogramConfiguration()
|
||||
{
|
||||
LabelNames = new[] { "type" },
|
||||
Buckets = Histogram.ExponentialBuckets(1, 2, 14),
|
||||
});
|
||||
|
||||
|
||||
[Dependency] private readonly IPlayerManager _player = default!;
|
||||
[Dependency] private readonly IConnectionManager _connection = default!;
|
||||
[Dependency] private readonly IConfigurationManager _configuration = default!;
|
||||
[Dependency] private readonly IServerNetManager _net = default!;
|
||||
[Dependency] private readonly LinkAccountManager _linkAccount = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Queue of active player sessions
|
||||
/// </summary>
|
||||
private readonly List<ICommonSession> _queue = new();
|
||||
|
||||
/// <summary>
|
||||
/// Queue for Patreon supporters.
|
||||
/// </summary>
|
||||
private readonly List<ICommonSession> _patronQueue = new();
|
||||
|
||||
private bool _isEnabled = false;
|
||||
private bool _patreonIsEnabled = true;
|
||||
|
||||
public int PlayerInQueueCount => _queue.Count + _patronQueue.Count;
|
||||
public int ActualPlayersCount => _player.PlayerCount - PlayerInQueueCount; // Now it's only real value with actual players count that in game
|
||||
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
_net.RegisterNetMessage<QueueUpdateMessage>();
|
||||
|
||||
_configuration.OnValueChanged(GoobCVars.QueueEnabled, OnQueueCVarChanged, true);
|
||||
_configuration.OnValueChanged(GoobCVars.PatreonSkip, OnPatronCvarChanged, true);
|
||||
_player.PlayerStatusChanged += OnPlayerStatusChanged;
|
||||
}
|
||||
|
||||
|
||||
private void OnQueueCVarChanged(bool value)
|
||||
{
|
||||
_isEnabled = value;
|
||||
|
||||
if (!value)
|
||||
{
|
||||
foreach (var session in _queue)
|
||||
session.Channel.Disconnect("Queue was disabled");
|
||||
foreach (var session in _patronQueue)
|
||||
session.Channel.Disconnect("Queue was disabled");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPatronCvarChanged(bool value)
|
||||
=> _patreonIsEnabled = value;
|
||||
|
||||
|
||||
private async void OnPlayerStatusChanged(object? sender, SessionStatusEventArgs e)
|
||||
{
|
||||
if (e.NewStatus == SessionStatus.Disconnected)
|
||||
{
|
||||
var wasInQueue = _queue.Remove(e.Session) || _patronQueue.Remove(e.Session);
|
||||
|
||||
if (!wasInQueue && e.OldStatus != SessionStatus.InGame) // Process queue only if player disconnected from InGame or from queue
|
||||
return;
|
||||
|
||||
ProcessQueue(true, e.Session.ConnectedTime);
|
||||
|
||||
if (wasInQueue)
|
||||
QueueTimings.WithLabels("Unwaited").Observe((DateTime.UtcNow - e.Session.ConnectedTime).TotalSeconds);
|
||||
}
|
||||
else if (e.NewStatus == SessionStatus.Connected)
|
||||
{
|
||||
OnPlayerConnected(e.Session);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private async void OnPlayerConnected(ICommonSession session)
|
||||
{
|
||||
if (!_isEnabled)
|
||||
{
|
||||
SendToGame(session);
|
||||
return;
|
||||
}
|
||||
|
||||
var isPrivileged = await _connection.HasPrivilegedJoin(session.UserId);
|
||||
var isPatron = _linkAccount.GetPatron(session)?.Tier != null;
|
||||
var currentOnline = _player.PlayerCount - 1;
|
||||
var haveFreeSlot = currentOnline < _configuration.GetCVar(CCVars.SoftMaxPlayers);
|
||||
if (isPrivileged || haveFreeSlot)
|
||||
{
|
||||
SendToGame(session);
|
||||
|
||||
if (isPrivileged && !haveFreeSlot)
|
||||
QueueBypassCount.Inc();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (isPatron && _patreonIsEnabled)
|
||||
_patronQueue.Add(session);
|
||||
else
|
||||
_queue.Add(session);
|
||||
|
||||
ProcessQueue(false, session.ConnectedTime);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If possible, takes the first player in the queue and sends him into the game
|
||||
/// </summary>
|
||||
/// <param name="isDisconnect">Is method called on disconnect event</param>
|
||||
/// <param name="connectedTime">Session connected time for histogram metrics</param>
|
||||
private void ProcessQueue(bool isDisconnect, DateTime connectedTime)
|
||||
{
|
||||
var players = ActualPlayersCount;
|
||||
if (isDisconnect)
|
||||
players--; // Decrease currently disconnected session but that has not yet been deleted
|
||||
|
||||
var haveFreeSlot = players < _configuration.GetCVar(CCVars.SoftMaxPlayers);
|
||||
var patronQueueContains = _patronQueue.Count > 0;
|
||||
var regularQueueContains = _queue.Count > 0;
|
||||
|
||||
if (haveFreeSlot && (patronQueueContains || regularQueueContains))
|
||||
{
|
||||
ICommonSession session;
|
||||
if (patronQueueContains)
|
||||
{
|
||||
session = _patronQueue.First();
|
||||
_patronQueue.Remove(session);
|
||||
}
|
||||
else
|
||||
{
|
||||
session = _queue.First();
|
||||
_queue.Remove(session);
|
||||
}
|
||||
|
||||
SendToGame(session);
|
||||
QueueTimings.WithLabels("Waited").Observe((DateTime.UtcNow - connectedTime).TotalSeconds);
|
||||
}
|
||||
|
||||
SendUpdateMessages();
|
||||
QueueCount.Set(_queue.Count + _patronQueue.Count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends messages to all players in the queue with the current state of the queue
|
||||
/// </summary>
|
||||
private void SendUpdateMessages()
|
||||
{
|
||||
var totalInQueue = _patronQueue.Count + _queue.Count;
|
||||
var currentPosition = 1;
|
||||
|
||||
for (var i = 0; i < _patronQueue.Count; i++, currentPosition++)
|
||||
{
|
||||
_patronQueue[i].Channel.SendMessage(new QueueUpdateMessage
|
||||
{
|
||||
Total = totalInQueue,
|
||||
Position = currentPosition,
|
||||
IsPatron = true,
|
||||
});
|
||||
}
|
||||
|
||||
for (var i = 0; i < _queue.Count; i++, currentPosition++)
|
||||
{
|
||||
_queue[i].Channel.SendMessage(new QueueUpdateMessage
|
||||
{
|
||||
Total = totalInQueue,
|
||||
Position = currentPosition,
|
||||
IsPatron = false,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Letting player's session into game, change player state
|
||||
/// </summary>
|
||||
/// <param name="session">Player session that will be sent to game</param>
|
||||
private void SendToGame(ICommonSession session)
|
||||
{
|
||||
|
||||
Timer.Spawn(0, () => _player.JoinGame(session));
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
namespace Content.Goobstation.Server.Weapons.BatterySlotRequiresItemToggle;
|
||||
namespace Content.Server._Goobstation.Weapons.BatterySlotRequiresItemToggle;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class BatterySlotRequiresToggleComponent : Component
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
using Content.Shared.Containers.ItemSlots;
|
||||
using Content.Shared.Item.ItemToggle.Components;
|
||||
|
||||
namespace Content.Goobstation.Server.Weapons.BatterySlotRequiresItemToggle;
|
||||
namespace Content.Server._Goobstation.Weapons.BatterySlotRequiresItemToggle;
|
||||
|
||||
public sealed class BatterySlotRequiresToggleSystem : EntitySystem
|
||||
{
|
||||
|
||||
@@ -0,0 +1,280 @@
|
||||
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.Database;
|
||||
using Content.Shared._RMC14.LinkAccount;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Timing;
|
||||
using Color = System.Drawing.Color;
|
||||
|
||||
namespace Content.Server._RMC14.LinkAccount;
|
||||
|
||||
public sealed class LinkAccountManager : IPostInjectInit
|
||||
{
|
||||
[Dependency] private readonly IServerDbManager _db = default!;
|
||||
[Dependency] private readonly INetManager _net = default!;
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly UserDbDataManager _userDb = default!;
|
||||
|
||||
private readonly Dictionary<NetUserId, TimeSpan> _lastRequest = new();
|
||||
private readonly TimeSpan _minimumWait = TimeSpan.FromSeconds(0.5);
|
||||
private readonly Dictionary<NetUserId, SharedRMCPatronFull> _connected = new();
|
||||
private readonly Dictionary<string, SharedRMCPatronTier> _fauxTiers = new();
|
||||
private readonly Dictionary<NetUserId, string> _fauxPatronAssignments = new();
|
||||
private readonly List<SharedRMCPatron> _allPatrons = [];
|
||||
private readonly List<(string Message, string User)> _lobbyMessages = [];
|
||||
private readonly List<string> _shoutouts = [];
|
||||
|
||||
public event Action? PatronsReloaded;
|
||||
public event Action<(NetUserId Id, SharedRMCPatronFull Patron)>? PatronUpdated;
|
||||
|
||||
private async Task LoadData(ICommonSession player, CancellationToken cancel)
|
||||
{
|
||||
var patron = await _db.GetPatron(player.UserId, cancel);
|
||||
var linked = await _db.HasLinkedAccount(player.UserId, cancel);
|
||||
cancel.ThrowIfCancellationRequested();
|
||||
|
||||
var tier = patron?.Tier;
|
||||
var sharedTier = tier == null
|
||||
? null
|
||||
: new SharedRMCPatronTier(
|
||||
tier.ShowOnCredits,
|
||||
tier.GhostColor,
|
||||
tier.LobbyMessage,
|
||||
tier.RoundEndShoutout,
|
||||
tier.Name,
|
||||
tier.Icon
|
||||
);
|
||||
|
||||
SharedRMCLobbyMessage? lobbyMessage = null;
|
||||
if (patron?.LobbyMessage is { Message.Length: > 0 } patronMsg)
|
||||
lobbyMessage = new SharedRMCLobbyMessage(patronMsg.Message);
|
||||
|
||||
var ntName = patron?.RoundEndNTShoutout?.Name;
|
||||
SharedRMCRoundEndShoutouts? shoutouts = null;
|
||||
if (ntName != null)
|
||||
shoutouts = new SharedRMCRoundEndShoutouts(ntName);
|
||||
|
||||
|
||||
Robust.Shared.Maths.Color? ghostColor = null;
|
||||
if (patron?.GhostColor is { } patronColor)
|
||||
{
|
||||
var sysColor = Color.FromArgb(patronColor);
|
||||
ghostColor = new Robust.Shared.Maths.Color(sysColor.R, sysColor.G, sysColor.B, sysColor.A);
|
||||
}
|
||||
|
||||
_connected[player.UserId] = new SharedRMCPatronFull(sharedTier, linked, ghostColor, lobbyMessage, shoutouts);
|
||||
}
|
||||
|
||||
private void FinishLoad(ICommonSession player)
|
||||
{
|
||||
SendPatronStatus(player);
|
||||
}
|
||||
|
||||
private void ClientDisconnected(ICommonSession player)
|
||||
{
|
||||
_connected.Remove(player.UserId);
|
||||
}
|
||||
|
||||
private void SendPatronStatus(ICommonSession player)
|
||||
{
|
||||
var connected = _connected.GetValueOrDefault(player.UserId);
|
||||
var msg = new LinkAccountStatusMsg { Patron = connected, };
|
||||
_net.ServerSendMessage(msg, player.Channel);
|
||||
SendPatrons(player);
|
||||
}
|
||||
|
||||
private void OnRequest(LinkAccountRequestMsg message)
|
||||
{
|
||||
var user = message.MsgChannel.UserId;
|
||||
var time = _timing.RealTime;
|
||||
if (_lastRequest.TryGetValue(user, out var last) &&
|
||||
last + _minimumWait > time)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_lastRequest[user] = time;
|
||||
|
||||
var code = Guid.NewGuid();
|
||||
_db.SetLinkingCode(user, code);
|
||||
|
||||
var response = new LinkAccountCodeMsg { Code = code };
|
||||
_net.ServerSendMessage(response, message.MsgChannel);
|
||||
}
|
||||
|
||||
private void OnClearGhostColor(RMCClearGhostColorMsg message)
|
||||
{
|
||||
SetGhostColor(message.MsgChannel.UserId, null);
|
||||
}
|
||||
|
||||
private void OnChangeGhostColor(RMCChangeGhostColorMsg message)
|
||||
{
|
||||
SetGhostColor(message.MsgChannel.UserId, message.Color);
|
||||
}
|
||||
|
||||
private void OnChangeLobbyMessage(RMCChangeLobbyMessageMsg message)
|
||||
{
|
||||
var text = message.Text;
|
||||
if (text == null)
|
||||
return;
|
||||
|
||||
var user = message.MsgChannel.UserId;
|
||||
if (GetPatron(user)?.Tier is not { LobbyMessage: true })
|
||||
return;
|
||||
|
||||
if (text.Length > SharedRMCLobbyMessage.CharacterLimit)
|
||||
text = text[..SharedRMCLobbyMessage.CharacterLimit];
|
||||
|
||||
_db.SetLobbyMessage(user, text);
|
||||
}
|
||||
|
||||
private void OnChangeNTShoutout(RMCChangeNTShoutoutMsg message)
|
||||
{
|
||||
var name = message.Name;
|
||||
if (name == null)
|
||||
return;
|
||||
|
||||
var user = message.MsgChannel.UserId;
|
||||
if (GetPatron(user)?.Tier is not { RoundEndShoutout: true })
|
||||
return;
|
||||
|
||||
if (name.Length > SharedRMCRoundEndShoutouts.CharacterLimit)
|
||||
name = name[..SharedRMCRoundEndShoutouts.CharacterLimit];
|
||||
|
||||
_db.SetNTShoutout(user, name);
|
||||
}
|
||||
|
||||
private void SetGhostColor(NetUserId user, Robust.Shared.Maths.Color? color)
|
||||
{
|
||||
if (GetPatron(user)?.Tier is not { GhostColor: true })
|
||||
return;
|
||||
|
||||
Color? sysColor = color == null ? null : Color.FromArgb(color.Value.ToArgb());
|
||||
_db.SetGhostColor(user, sysColor);
|
||||
|
||||
if (_connected.TryGetValue(user, out var connected))
|
||||
{
|
||||
connected = connected with { GhostColor = color };
|
||||
_connected[user] = connected;
|
||||
PatronUpdated?.Invoke((user, connected));
|
||||
}
|
||||
}
|
||||
|
||||
public async Task RefreshAllPatrons()
|
||||
{
|
||||
var patrons = await _db.GetAllPatrons();
|
||||
var messages = await _db.GetLobbyMessages();
|
||||
var shoutouts = await _db.GetShoutouts();
|
||||
|
||||
_allPatrons.Clear();
|
||||
_lobbyMessages.Clear();
|
||||
_shoutouts.Clear();
|
||||
|
||||
foreach (var patron in patrons)
|
||||
{
|
||||
_allPatrons.Add(new SharedRMCPatron(patron.Player.LastSeenUserName, patron.Tier.Name));
|
||||
}
|
||||
|
||||
_lobbyMessages.AddRange(messages);
|
||||
_shoutouts.AddRange(shoutouts);
|
||||
|
||||
PatronsReloaded?.Invoke();
|
||||
}
|
||||
|
||||
public (string Message, string User)? GetRandomLobbyMessage()
|
||||
{
|
||||
if (_lobbyMessages.Count == 0)
|
||||
return null;
|
||||
|
||||
return _random.Pick(_lobbyMessages);
|
||||
}
|
||||
|
||||
public string GetRandomShoutout()
|
||||
{
|
||||
if (_shoutouts.Count == 0)
|
||||
return "John Nanotrasen";
|
||||
|
||||
return _random.Pick(_shoutouts);
|
||||
}
|
||||
|
||||
public void SendPatronsToAll()
|
||||
{
|
||||
var msg = new RMCPatronListMsg { Patrons = _allPatrons };
|
||||
_net.ServerSendToAll(msg);
|
||||
}
|
||||
|
||||
public void SendPatrons(ICommonSession player)
|
||||
{
|
||||
var msg = new RMCPatronListMsg { Patrons = _allPatrons };
|
||||
_net.ServerSendMessage(msg, player.Channel);
|
||||
}
|
||||
|
||||
public SharedRMCPatronFull? GetPatron(ICommonSession player)
|
||||
{
|
||||
return GetPatron(player.UserId);
|
||||
}
|
||||
|
||||
public SharedRMCPatronFull? GetPatron(NetUserId userId)
|
||||
{
|
||||
if (_fauxPatronAssignments.TryGetValue(userId, out var tierId) &&
|
||||
_fauxTiers.TryGetValue(tierId, out var tier))
|
||||
{
|
||||
return new SharedRMCPatronFull(
|
||||
Tier: tier,
|
||||
Linked: true,
|
||||
GhostColor: null,
|
||||
LobbyMessage: null,
|
||||
RoundEndShoutout: null
|
||||
);
|
||||
}
|
||||
|
||||
return _connected.GetValueOrDefault(userId);
|
||||
}
|
||||
|
||||
public void AddFauxTier(string tierId, SharedRMCPatronTier tier)
|
||||
{
|
||||
_fauxTiers[tierId] = tier;
|
||||
}
|
||||
|
||||
public bool RemoveFauxTier(string tierId)
|
||||
{
|
||||
return _fauxTiers.Remove(tierId);
|
||||
}
|
||||
|
||||
public void AssignFauxPatron(NetUserId userId, string? tierId)
|
||||
{
|
||||
if (tierId == null)
|
||||
_fauxPatronAssignments.Remove(userId);
|
||||
else if (_fauxTiers.ContainsKey(tierId))
|
||||
_fauxPatronAssignments[userId] = tierId;
|
||||
}
|
||||
|
||||
public Dictionary<string, SharedRMCPatronTier> GetAllFauxTiers()
|
||||
{
|
||||
return _fauxTiers;
|
||||
}
|
||||
|
||||
public Dictionary<NetUserId, string> GetAllFauxPatronAssignments()
|
||||
{
|
||||
return _fauxPatronAssignments;
|
||||
}
|
||||
|
||||
void IPostInjectInit.PostInject()
|
||||
{
|
||||
_net.RegisterNetMessage<LinkAccountRequestMsg>(OnRequest);
|
||||
_net.RegisterNetMessage<LinkAccountCodeMsg>();
|
||||
_net.RegisterNetMessage<LinkAccountStatusMsg>();
|
||||
_net.RegisterNetMessage<RMCPatronListMsg>();
|
||||
_net.RegisterNetMessage<RMCClearGhostColorMsg>(OnClearGhostColor);
|
||||
_net.RegisterNetMessage<RMCChangeGhostColorMsg>(OnChangeGhostColor);
|
||||
_net.RegisterNetMessage<RMCChangeLobbyMessageMsg>(OnChangeLobbyMessage);
|
||||
_net.RegisterNetMessage<RMCChangeNTShoutoutMsg>(OnChangeNTShoutout);
|
||||
_userDb.AddOnLoadPlayer(LoadData);
|
||||
_userDb.AddOnFinishLoad(FinishLoad);
|
||||
_userDb.AddOnPlayerDisconnect(ClientDisconnected);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
using Content.Server.Chat.Managers;
|
||||
using Content.Server.Chat.Systems;
|
||||
using Content.Server.Database;
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Server.RoundEnd;
|
||||
using Content.Shared._Goobstation.CCVars;
|
||||
using Content.Shared._RMC14.GhostColor;
|
||||
using Content.Shared._RMC14.LinkAccount;
|
||||
using Content.Shared.GameTicking;
|
||||
using Content.Shared.Ghost;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Server._RMC14.LinkAccount;
|
||||
|
||||
public sealed class LinkAccountSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IConfigurationManager _config = default!;
|
||||
[Dependency] private readonly IServerDbManager _db = default!;
|
||||
[Dependency] private readonly LinkAccountManager _linkAccount = default!;
|
||||
[Dependency] private readonly IPlayerManager _player = default!;
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
|
||||
private TimeSpan _timeBetweenLobbyMessages;
|
||||
private TimeSpan _nextLobbyMessageTime;
|
||||
private TimeSpan _lobbyMessageInitialDelay;
|
||||
private (string Message, string User)? _nextLobbyMessage;
|
||||
private string? _nextNTShoutout;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<GameRunLevelChangedEvent>(OnGameRunLevelChanged);
|
||||
SubscribeLocalEvent<RoundEndTextAppendEvent>(OnRoundEndTextAppend);
|
||||
|
||||
SubscribeLocalEvent<GhostColorComponent, PlayerAttachedEvent>(OnGhostColorPlayerAttached);
|
||||
|
||||
Subs.CVar(_config, GoobCVars.RMCPatronLobbyMessageTimeSeconds, v => _timeBetweenLobbyMessages = TimeSpan.FromSeconds(v), true);
|
||||
Subs.CVar(_config, GoobCVars.RMCPatronLobbyMessageInitialDelaySeconds, v => _lobbyMessageInitialDelay = TimeSpan.FromSeconds(v), true);
|
||||
|
||||
ReloadPatrons();
|
||||
GetRandomLobbyMessage();
|
||||
GetRandomShoutout();
|
||||
|
||||
_linkAccount.PatronUpdated += OnPatronUpdated;
|
||||
}
|
||||
|
||||
public override void Shutdown()
|
||||
{
|
||||
_linkAccount.PatronUpdated -= OnPatronUpdated;
|
||||
}
|
||||
|
||||
private void OnGameRunLevelChanged(GameRunLevelChangedEvent ev)
|
||||
{
|
||||
switch (ev.New)
|
||||
{
|
||||
case GameRunLevel.InRound:
|
||||
GetRandomShoutout();
|
||||
break;
|
||||
case GameRunLevel.PreRoundLobby:
|
||||
case GameRunLevel.PostRound:
|
||||
ReloadPatrons();
|
||||
GetRandomLobbyMessage();
|
||||
GetRandomShoutout();
|
||||
break;
|
||||
}
|
||||
|
||||
if (ev.New == GameRunLevel.PreRoundLobby)
|
||||
_nextLobbyMessageTime = _timing.RealTime + _lobbyMessageInitialDelay;
|
||||
}
|
||||
|
||||
private void OnRoundEndTextAppend(RoundEndTextAppendEvent ev)
|
||||
{
|
||||
if (_nextNTShoutout != null)
|
||||
{
|
||||
ev.AddLine("\n");
|
||||
ev.AddLine(Loc.GetString("rmc-ui-shoutout-nt", ("name", _nextNTShoutout)));
|
||||
}
|
||||
}
|
||||
|
||||
private void OnGhostColorPlayerAttached(Entity<GhostColorComponent> ent, ref PlayerAttachedEvent args)
|
||||
{
|
||||
if (!TryComp(ent, out ActorComponent? actor) ||
|
||||
_linkAccount.GetPatron(actor.PlayerSession.UserId) is not { } patron ||
|
||||
patron.Tier is not { GhostColor: true } ||
|
||||
patron.GhostColor is not { } color)
|
||||
{
|
||||
RemCompDeferred<GhostColorComponent>(ent);
|
||||
return;
|
||||
}
|
||||
|
||||
ent.Comp.Color = color;
|
||||
Dirty(ent);
|
||||
}
|
||||
|
||||
private async void ReloadPatrons()
|
||||
{
|
||||
try
|
||||
{
|
||||
await _linkAccount.RefreshAllPatrons();
|
||||
_linkAccount.SendPatronsToAll();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error($"Error reloading Patrons list:\n{e}");
|
||||
}
|
||||
}
|
||||
|
||||
private void GetRandomLobbyMessage()
|
||||
{
|
||||
try
|
||||
{
|
||||
_nextLobbyMessage = _linkAccount.GetRandomLobbyMessage();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error($"Error getting random lobby message:\n{e}");
|
||||
}
|
||||
}
|
||||
|
||||
private void GetRandomShoutout()
|
||||
{
|
||||
try
|
||||
{
|
||||
_nextNTShoutout = _linkAccount.GetRandomShoutout();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error($"Error getting random shoutout:\n{e}");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPatronUpdated((NetUserId Id, SharedRMCPatronFull Patron) tuple)
|
||||
{
|
||||
if (_player.TryGetSessionById(tuple.Id, out var session) &&
|
||||
session.AttachedEntity is { } ent &&
|
||||
HasComp<GhostComponent>(ent))
|
||||
{
|
||||
var color = EnsureComp<GhostColorComponent>(ent);
|
||||
color.Color = tuple.Patron.GhostColor;
|
||||
Dirty(ent, color);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
var time = _timing.RealTime;
|
||||
if (time < _nextLobbyMessageTime)
|
||||
return;
|
||||
|
||||
_nextLobbyMessageTime = time + _timeBetweenLobbyMessages;
|
||||
|
||||
if (_nextLobbyMessage is { } message)
|
||||
RaiseNetworkEvent(new SharedRMCDisplayLobbyMessageEvent(message.Message, message.User));
|
||||
|
||||
GetRandomLobbyMessage();
|
||||
}
|
||||
}
|
||||
@@ -14,4 +14,40 @@ public sealed partial class GoobCVars
|
||||
CVarDef.Create("mech.gun_outside_mech", true, CVar.SERVER | CVar.REPLICATED);
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
#region RMC
|
||||
|
||||
public static readonly CVarDef<int> RMCPatronLobbyMessageTimeSeconds =
|
||||
CVarDef.Create("rmc.patron_lobby_message_time_seconds", 30, CVar.REPLICATED | CVar.SERVER);
|
||||
|
||||
public static readonly CVarDef<int> RMCPatronLobbyMessageInitialDelaySeconds =
|
||||
CVarDef.Create("rmc.patron_lobby_message_initial_delay_seconds", 5, CVar.REPLICATED | CVar.SERVER);
|
||||
|
||||
public static readonly CVarDef<string> RMCDiscordAccountLinkingMessageLink =
|
||||
CVarDef.Create("rmc.discord_account_linking_message_link", "", CVar.REPLICATED | CVar.SERVER);
|
||||
|
||||
#endregion
|
||||
|
||||
public static readonly CVarDef<string> PatronSupportLastShown =
|
||||
CVarDef.Create("patron.support_last_shown", "", CVar.CLIENTONLY | CVar.ARCHIVE);
|
||||
|
||||
public static readonly CVarDef<int> PatronAskSupport =
|
||||
CVarDef.Create("patron.ask_support", 7, CVar.REPLICATED | CVar.SERVER);
|
||||
|
||||
#region Queue
|
||||
|
||||
/// <summary>
|
||||
/// Controls if the connections queue is enabled
|
||||
/// If enabled plyaers will be added to a queue instead of being kicked after SoftMaxPlayers is reached
|
||||
/// </summary>
|
||||
public static readonly CVarDef<bool> QueueEnabled =
|
||||
CVarDef.Create("queue.enabled", false, CVar.SERVERONLY);
|
||||
|
||||
/// <summary>
|
||||
/// If enabled patrons will be sent to the front of the queue.
|
||||
/// </summary>
|
||||
public static readonly CVarDef<bool> PatreonSkip =
|
||||
CVarDef.Create("queue.patreon_skip", true, CVar.SERVERONLY);
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com>
|
||||
// SPDX-FileCopyrightText: 2025 GoobBot <uristmchands@proton.me>
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
namespace Content.Shared._Goobstation.JoinQueue;
|
||||
|
||||
/// <summary>
|
||||
/// Defines the public contract for managing the player join queue.
|
||||
/// </summary>
|
||||
public interface IJoinQueueManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes the join queue manager.
|
||||
/// </summary>
|
||||
void Initialize();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the total number of players currently waiting in any queue (patron or regular).
|
||||
/// </summary>
|
||||
int PlayerInQueueCount { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of players currently considered "in the game" (not in the queue).
|
||||
/// </summary>
|
||||
int ActualPlayersCount { get; }
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
// SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com>
|
||||
// SPDX-FileCopyrightText: 2025 GoobBot <uristmchands@proton.me>
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
using Lidgren.Network;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._Goobstation.JoinQueue;
|
||||
|
||||
/// <summary>
|
||||
/// Sent from server to client with queue state for player
|
||||
/// Also initiates queue state on client
|
||||
/// </summary>
|
||||
public sealed class QueueUpdateMessage : NetMessage
|
||||
{
|
||||
public override MsgGroups MsgGroup => MsgGroups.Command;
|
||||
|
||||
/// <summary>
|
||||
/// Total players in queue
|
||||
/// </summary>
|
||||
public int Total { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Player current position in queue (starts from 1)
|
||||
/// </summary>
|
||||
public int Position { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If player is a patron. Defaults to false.
|
||||
/// </summary>
|
||||
public bool IsPatron { get; set; } = false;
|
||||
|
||||
public override void ReadFromBuffer(NetIncomingMessage buffer, IRobustSerializer serializer)
|
||||
{
|
||||
Total = buffer.ReadInt32();
|
||||
Position = buffer.ReadInt32();
|
||||
IsPatron = buffer.ReadBoolean();
|
||||
}
|
||||
|
||||
public override void WriteToBuffer(NetOutgoingMessage buffer, IRobustSerializer serializer)
|
||||
{
|
||||
buffer.Write(Total);
|
||||
buffer.Write(Position);
|
||||
buffer.Write(IsPatron);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared._RMC14.GhostColor;
|
||||
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||
public sealed partial class GhostColorComponent : Component
|
||||
{
|
||||
[DataField, AutoNetworkedField]
|
||||
public Color? Color;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using Lidgren.Network;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._RMC14.LinkAccount;
|
||||
|
||||
public sealed class LinkAccountCodeMsg : NetMessage
|
||||
{
|
||||
public Guid Code;
|
||||
|
||||
public override MsgGroups MsgGroup => MsgGroups.Core;
|
||||
|
||||
public override void ReadFromBuffer(NetIncomingMessage buffer, IRobustSerializer serializer)
|
||||
{
|
||||
Code = buffer.ReadGuid();
|
||||
}
|
||||
|
||||
public override void WriteToBuffer(NetOutgoingMessage buffer, IRobustSerializer serializer)
|
||||
{
|
||||
buffer.Write(Code);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using Lidgren.Network;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._RMC14.LinkAccount;
|
||||
|
||||
public sealed class LinkAccountRequestMsg : NetMessage
|
||||
{
|
||||
public override MsgGroups MsgGroup => MsgGroups.Core;
|
||||
|
||||
public override void ReadFromBuffer(NetIncomingMessage buffer, IRobustSerializer serializer)
|
||||
{
|
||||
}
|
||||
|
||||
public override void WriteToBuffer(NetOutgoingMessage buffer, IRobustSerializer serializer)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using System.IO;
|
||||
using Lidgren.Network;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._RMC14.LinkAccount;
|
||||
|
||||
public sealed class LinkAccountStatusMsg : NetMessage
|
||||
{
|
||||
public override MsgGroups MsgGroup => MsgGroups.Core;
|
||||
|
||||
public SharedRMCPatronFull? Patron;
|
||||
|
||||
public override void ReadFromBuffer(NetIncomingMessage buffer, IRobustSerializer serializer)
|
||||
{
|
||||
var isPatron = buffer.ReadBoolean();
|
||||
if (!isPatron)
|
||||
return;
|
||||
|
||||
buffer.ReadPadBits();
|
||||
var length = buffer.ReadVariableInt32();
|
||||
using var stream = new MemoryStream(length);
|
||||
buffer.ReadAlignedMemory(stream, length);
|
||||
Patron = serializer.Deserialize<SharedRMCPatronFull>(stream);
|
||||
}
|
||||
|
||||
public override void WriteToBuffer(NetOutgoingMessage buffer, IRobustSerializer serializer)
|
||||
{
|
||||
if (Patron == null)
|
||||
{
|
||||
buffer.Write(false);
|
||||
return;
|
||||
}
|
||||
|
||||
buffer.Write(true);
|
||||
buffer.WritePadBits();
|
||||
using (var stream = new MemoryStream())
|
||||
{
|
||||
serializer.Serialize(stream, Patron);
|
||||
buffer.WriteVariableInt32((int) stream.Length);
|
||||
stream.TryGetBuffer(out var segment);
|
||||
buffer.Write(segment);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using Lidgren.Network;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._RMC14.LinkAccount;
|
||||
|
||||
public sealed class RMCChangeGhostColorMsg : NetMessage
|
||||
{
|
||||
public override MsgGroups MsgGroup => MsgGroups.Command;
|
||||
|
||||
public Color Color;
|
||||
|
||||
public override void ReadFromBuffer(NetIncomingMessage buffer, IRobustSerializer serializer)
|
||||
{
|
||||
Color = buffer.ReadColor();
|
||||
}
|
||||
|
||||
public override void WriteToBuffer(NetOutgoingMessage buffer, IRobustSerializer serializer)
|
||||
{
|
||||
buffer.Write(Color);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using Lidgren.Network;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._RMC14.LinkAccount;
|
||||
|
||||
public sealed class RMCChangeLobbyMessageMsg : NetMessage
|
||||
{
|
||||
public override MsgGroups MsgGroup => MsgGroups.Command;
|
||||
|
||||
public string? Text;
|
||||
|
||||
public override void ReadFromBuffer(NetIncomingMessage buffer, IRobustSerializer serializer)
|
||||
{
|
||||
if (buffer.PeekStringSize() > 10000)
|
||||
return;
|
||||
|
||||
Text = buffer.ReadString();
|
||||
}
|
||||
|
||||
public override void WriteToBuffer(NetOutgoingMessage buffer, IRobustSerializer serializer)
|
||||
{
|
||||
buffer.Write(Text);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user