[feat] donate
# Conflicts: # Content.Client/Entry/EntryPoint.cs # Content.Client/IoC/ClientContentIoC.cs # Content.Server/Chat/Managers/ChatManager.cs # Content.Server/Entry/EntryPoint.cs # Content.Server/GameTicking/GameTicker.Player.cs # Content.Server/GameTicking/GameTicker.StatusShell.cs # Content.Server/IoC/ServerContentIoC.cs # Content.Shared/Humanoid/HumanoidCharacterAppearance.cs # Content.Shared/Humanoid/Markings/MarkingPrototype.cs # Content.Shared/Preferences/HumanoidCharacterProfile.cs
This commit is contained in:
@@ -21,6 +21,8 @@ using Content.Client.Singularity;
|
|||||||
using Content.Client.Stylesheets;
|
using Content.Client.Stylesheets;
|
||||||
using Content.Client.Viewport;
|
using Content.Client.Viewport;
|
||||||
using Content.Client.Voting;
|
using Content.Client.Voting;
|
||||||
|
using Content.Client.White.JoinQueue;
|
||||||
|
using Content.Client.White.Sponsors;
|
||||||
using Content.Shared.Ame;
|
using Content.Shared.Ame;
|
||||||
using Content.Shared.Gravity;
|
using Content.Shared.Gravity;
|
||||||
using Content.Shared.Localizations;
|
using Content.Shared.Localizations;
|
||||||
@@ -71,6 +73,11 @@ namespace Content.Client.Entry
|
|||||||
[Dependency] private readonly IReplayLoadManager _replayLoad = default!;
|
[Dependency] private readonly IReplayLoadManager _replayLoad = default!;
|
||||||
[Dependency] private readonly ILogManager _logManager = default!;
|
[Dependency] private readonly ILogManager _logManager = default!;
|
||||||
|
|
||||||
|
//WD-EDIT
|
||||||
|
[Dependency] private readonly SponsorsManager _sponsorsManager = default!;
|
||||||
|
[Dependency] private readonly JoinQueueManager _queueManager = default!;
|
||||||
|
//WD-EDIT
|
||||||
|
|
||||||
public override void Init()
|
public override void Init()
|
||||||
{
|
{
|
||||||
ClientContentIoC.Register();
|
ClientContentIoC.Register();
|
||||||
@@ -163,6 +170,11 @@ namespace Content.Client.Entry
|
|||||||
_userInterfaceManager.SetActiveTheme(_configManager.GetCVar(CVars.InterfaceTheme));
|
_userInterfaceManager.SetActiveTheme(_configManager.GetCVar(CVars.InterfaceTheme));
|
||||||
_documentParsingManager.Initialize();
|
_documentParsingManager.Initialize();
|
||||||
|
|
||||||
|
//WD-EDIT
|
||||||
|
_sponsorsManager.Initialize();
|
||||||
|
_queueManager.Initialize();
|
||||||
|
//WD-EDIT
|
||||||
|
|
||||||
_baseClient.RunLevelChanged += (_, args) =>
|
_baseClient.RunLevelChanged += (_, args) =>
|
||||||
{
|
{
|
||||||
if (args.NewLevel == ClientRunLevel.Initialize)
|
if (args.NewLevel == ClientRunLevel.Initialize)
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Content.Client.White.Sponsors;
|
||||||
using Content.Shared.Humanoid;
|
using Content.Shared.Humanoid;
|
||||||
using Content.Shared.Humanoid.Markings;
|
using Content.Shared.Humanoid.Markings;
|
||||||
using Content.Shared.Humanoid.Prototypes;
|
using Content.Shared.Humanoid.Prototypes;
|
||||||
@@ -19,6 +20,10 @@ public sealed partial class MarkingPicker : Control
|
|||||||
[Dependency] private readonly MarkingManager _markingManager = default!;
|
[Dependency] private readonly MarkingManager _markingManager = default!;
|
||||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||||
|
|
||||||
|
//WD-EDIT
|
||||||
|
[Dependency] private readonly SponsorsManager _sponsorsManager = default!;
|
||||||
|
//WD-EDIT
|
||||||
|
|
||||||
public Action<MarkingSet>? OnMarkingAdded;
|
public Action<MarkingSet>? OnMarkingAdded;
|
||||||
public Action<MarkingSet>? OnMarkingRemoved;
|
public Action<MarkingSet>? OnMarkingRemoved;
|
||||||
public Action<MarkingSet>? OnMarkingColorChange;
|
public Action<MarkingSet>? OnMarkingColorChange;
|
||||||
@@ -202,6 +207,18 @@ public sealed partial class MarkingPicker : Control
|
|||||||
|
|
||||||
var item = CMarkingsUnused.AddItem($"{GetMarkingName(marking)}", marking.Sprites[0].Frame0());
|
var item = CMarkingsUnused.AddItem($"{GetMarkingName(marking)}", marking.Sprites[0].Frame0());
|
||||||
item.Metadata = marking;
|
item.Metadata = marking;
|
||||||
|
|
||||||
|
//WD-EDIT
|
||||||
|
if (marking.SponsorOnly)
|
||||||
|
{
|
||||||
|
item.Disabled = true;
|
||||||
|
if (_sponsorsManager.TryGetInfo(out var sponsor))
|
||||||
|
{
|
||||||
|
item.Disabled = !sponsor.AllowedMarkings.Contains(marking.ID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//WD-EDIT
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CMarkingPoints.Visible = _currentMarkings.PointsLeft(_selectedMarkingCategory) != -1;
|
CMarkingPoints.Visible = _currentMarkings.PointsLeft(_selectedMarkingCategory) != -1;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Content.Client.White.Sponsors;
|
||||||
using Content.Shared.Humanoid.Markings;
|
using Content.Shared.Humanoid.Markings;
|
||||||
using Robust.Client.AutoGenerated;
|
using Robust.Client.AutoGenerated;
|
||||||
using Robust.Client.UserInterface.Controls;
|
using Robust.Client.UserInterface.Controls;
|
||||||
@@ -12,6 +13,10 @@ public sealed partial class SingleMarkingPicker : BoxContainer
|
|||||||
{
|
{
|
||||||
[Dependency] private readonly MarkingManager _markingManager = default!;
|
[Dependency] private readonly MarkingManager _markingManager = default!;
|
||||||
|
|
||||||
|
//WD-EDIT
|
||||||
|
[Dependency] private readonly SponsorsManager _sponsorsManager = default!;
|
||||||
|
//WD-EDIT
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// What happens if a marking is selected.
|
/// What happens if a marking is selected.
|
||||||
/// It will send the 'slot' (marking index)
|
/// It will send the 'slot' (marking index)
|
||||||
@@ -191,6 +196,17 @@ public sealed partial class SingleMarkingPicker : BoxContainer
|
|||||||
var item = MarkingList.AddItem(Loc.GetString($"marking-{id}"), marking.Sprites[0].Frame0());
|
var item = MarkingList.AddItem(Loc.GetString($"marking-{id}"), marking.Sprites[0].Frame0());
|
||||||
item.Metadata = marking.ID;
|
item.Metadata = marking.ID;
|
||||||
|
|
||||||
|
//WD-EDIT
|
||||||
|
if (marking.SponsorOnly)
|
||||||
|
{
|
||||||
|
item.Disabled = true;
|
||||||
|
if (_sponsorsManager.TryGetInfo(out var sponsor))
|
||||||
|
{
|
||||||
|
item.Disabled = !sponsor.AllowedMarkings.Contains(marking.ID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//WD-EDIT
|
||||||
|
|
||||||
if (_markings[Slot].MarkingId == id)
|
if (_markings[Slot].MarkingId == id)
|
||||||
{
|
{
|
||||||
_ignoreItemSelected = true;
|
_ignoreItemSelected = true;
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ using Content.Client.Administration.Managers;
|
|||||||
using Content.Client.Changelog;
|
using Content.Client.Changelog;
|
||||||
using Content.Client.Chat.Managers;
|
using Content.Client.Chat.Managers;
|
||||||
using Content.Client.Clickable;
|
using Content.Client.Clickable;
|
||||||
using Content.Client.Options;
|
|
||||||
using Content.Client.Eui;
|
using Content.Client.Eui;
|
||||||
using Content.Client.GhostKick;
|
using Content.Client.GhostKick;
|
||||||
using Content.Client.Info;
|
using Content.Client.Info;
|
||||||
@@ -15,14 +14,13 @@ using Content.Client.Fullscreen;
|
|||||||
using Content.Client.Stylesheets;
|
using Content.Client.Stylesheets;
|
||||||
using Content.Client.Viewport;
|
using Content.Client.Viewport;
|
||||||
using Content.Client.Voting;
|
using Content.Client.Voting;
|
||||||
using Content.Shared.Administration;
|
|
||||||
using Content.Shared.Administration.Logs;
|
using Content.Shared.Administration.Logs;
|
||||||
using Content.Shared.Module;
|
|
||||||
using Content.Client.Guidebook;
|
using Content.Client.Guidebook;
|
||||||
using Content.Client.Replay;
|
using Content.Client.Replay;
|
||||||
|
using Content.Client.White.JoinQueue;
|
||||||
|
using Content.Client.White.Sponsors;
|
||||||
using Content.Shared.Administration.Managers;
|
using Content.Shared.Administration.Managers;
|
||||||
|
|
||||||
|
|
||||||
namespace Content.Client.IoC
|
namespace Content.Client.IoC
|
||||||
{
|
{
|
||||||
internal static class ClientContentIoC
|
internal static class ClientContentIoC
|
||||||
@@ -49,6 +47,11 @@ namespace Content.Client.IoC
|
|||||||
IoCManager.Register<JobRequirementsManager>();
|
IoCManager.Register<JobRequirementsManager>();
|
||||||
IoCManager.Register<DocumentParsingManager>();
|
IoCManager.Register<DocumentParsingManager>();
|
||||||
IoCManager.Register<ContentReplayPlaybackManager, ContentReplayPlaybackManager>();
|
IoCManager.Register<ContentReplayPlaybackManager, ContentReplayPlaybackManager>();
|
||||||
|
|
||||||
|
//WD-EDIT
|
||||||
|
IoCManager.Register<JoinQueueManager>();
|
||||||
|
IoCManager.Register<SponsorsManager>();
|
||||||
|
//WD-EDIT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Content.Client.White.Sponsors;
|
||||||
using Content.Shared.Preferences;
|
using Content.Shared.Preferences;
|
||||||
using Robust.Client;
|
using Robust.Client;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
@@ -19,6 +20,10 @@ namespace Content.Client.Preferences
|
|||||||
[Dependency] private readonly IClientNetManager _netManager = default!;
|
[Dependency] private readonly IClientNetManager _netManager = default!;
|
||||||
[Dependency] private readonly IBaseClient _baseClient = default!;
|
[Dependency] private readonly IBaseClient _baseClient = default!;
|
||||||
|
|
||||||
|
//WD-EDIT
|
||||||
|
[Dependency] private readonly SponsorsManager _sponsorsManager = default!;
|
||||||
|
//WD-EDIT
|
||||||
|
|
||||||
public event Action? OnServerDataLoaded;
|
public event Action? OnServerDataLoaded;
|
||||||
|
|
||||||
public GameSettings Settings { get; private set; } = default!;
|
public GameSettings Settings { get; private set; } = default!;
|
||||||
@@ -60,7 +65,10 @@ namespace Content.Client.Preferences
|
|||||||
|
|
||||||
public void UpdateCharacter(ICharacterProfile profile, int slot)
|
public void UpdateCharacter(ICharacterProfile profile, int slot)
|
||||||
{
|
{
|
||||||
profile.EnsureValid();
|
//WD-EDIT
|
||||||
|
var allowedMarkings = _sponsorsManager.TryGetInfo(out var sponsor) ? sponsor.AllowedMarkings : new string[]{};
|
||||||
|
profile.EnsureValid(allowedMarkings);
|
||||||
|
//WD-EDIT
|
||||||
var characters = new Dictionary<int, ICharacterProfile>(Preferences.Characters) {[slot] = profile};
|
var characters = new Dictionary<int, ICharacterProfile>(Preferences.Characters) {[slot] = profile};
|
||||||
Preferences = new PlayerPreferences(characters, Preferences.SelectedCharacterIndex, Preferences.AdminOOCColor);
|
Preferences = new PlayerPreferences(characters, Preferences.SelectedCharacterIndex, Preferences.AdminOOCColor);
|
||||||
var msg = new MsgUpdateCharacter
|
var msg = new MsgUpdateCharacter
|
||||||
|
|||||||
26
Content.Client/White/JoinQueue/JoinQueueManager.cs
Normal file
26
Content.Client/White/JoinQueue/JoinQueueManager.cs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
using Content.Shared.White.JoinQueue;
|
||||||
|
using Robust.Client.State;
|
||||||
|
using Robust.Shared.Network;
|
||||||
|
|
||||||
|
namespace Content.Client.White.JoinQueue;
|
||||||
|
|
||||||
|
public sealed class JoinQueueManager
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IClientNetManager _netManager = default!;
|
||||||
|
[Dependency] private readonly IStateManager _stateManager = default!;
|
||||||
|
|
||||||
|
public void Initialize()
|
||||||
|
{
|
||||||
|
_netManager.RegisterNetMessage<MsgQueueUpdate>(OnQueueUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnQueueUpdate(MsgQueueUpdate msg)
|
||||||
|
{
|
||||||
|
if (_stateManager.CurrentState is not QueueState)
|
||||||
|
{
|
||||||
|
_stateManager.RequestStateChange<QueueState>();
|
||||||
|
}
|
||||||
|
|
||||||
|
((QueueState) _stateManager.CurrentState).OnQueueUpdate(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
34
Content.Client/White/JoinQueue/QueueGui.xaml
Normal file
34
Content.Client/White/JoinQueue/QueueGui.xaml
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
<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"
|
||||||
|
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls">
|
||||||
|
<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>
|
||||||
|
</BoxContainer>
|
||||||
|
</BoxContainer>
|
||||||
|
<BoxContainer Orientation="Horizontal" VerticalAlignment="Bottom" Margin="0 20 0 0">
|
||||||
|
<Button Name="PriorityJoinButton" Text="{Loc 'queue-priority-join'}" HorizontalExpand="True" StyleClasses="OpenRight" />
|
||||||
|
</BoxContainer>
|
||||||
|
</BoxContainer>
|
||||||
|
</Control>
|
||||||
|
</Control>
|
||||||
36
Content.Client/White/JoinQueue/QueueGui.xaml.cs
Normal file
36
Content.Client/White/JoinQueue/QueueGui.xaml.cs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
using Content.Shared.CCVar;
|
||||||
|
using Robust.Client.AutoGenerated;
|
||||||
|
using Robust.Client.UserInterface;
|
||||||
|
using Robust.Client.UserInterface.Controls;
|
||||||
|
using Robust.Client.UserInterface.XAML;
|
||||||
|
using Robust.Shared.Configuration;
|
||||||
|
|
||||||
|
|
||||||
|
namespace Content.Client.White.JoinQueue;
|
||||||
|
|
||||||
|
[GenerateTypedNameReferences]
|
||||||
|
public sealed partial class QueueGui : Control
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||||
|
|
||||||
|
public event Action? QuitPressed;
|
||||||
|
|
||||||
|
public QueueGui()
|
||||||
|
{
|
||||||
|
RobustXamlLoader.Load(this);
|
||||||
|
LayoutContainer.SetAnchorPreset(this, LayoutContainer.LayoutPreset.Wide);
|
||||||
|
|
||||||
|
QuitButton.OnPressed += (_) => QuitPressed?.Invoke();
|
||||||
|
PriorityJoinButton.OnPressed += (_) =>
|
||||||
|
{
|
||||||
|
var linkPatreon = _cfg.GetCVar(CCVars.InfoLinksPatreon);
|
||||||
|
IoCManager.Resolve<IUriOpener>().OpenUri(linkPatreon);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateInfo(int total, int position)
|
||||||
|
{
|
||||||
|
QueueTotal.Text = total.ToString();
|
||||||
|
QueuePosition.Text = position.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
53
Content.Client/White/JoinQueue/QueueState.cs
Normal file
53
Content.Client/White/JoinQueue/QueueState.cs
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
using Robust.Client.Console;
|
||||||
|
using Robust.Client.GameObjects;
|
||||||
|
using Robust.Client.State;
|
||||||
|
using Robust.Client.UserInterface;
|
||||||
|
using Robust.Shared.Player;
|
||||||
|
using Content.Shared.White.JoinQueue;
|
||||||
|
using Robust.Client.Audio;
|
||||||
|
|
||||||
|
namespace Content.Client.White.JoinQueue;
|
||||||
|
|
||||||
|
public sealed class QueueState : State
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IUserInterfaceManager _userInterfaceManager = default!;
|
||||||
|
[Dependency] private readonly IClientConsoleHost _consoleHost = default!;
|
||||||
|
|
||||||
|
private const string JoinSoundPath = "/Audio/Effects/voteding.ogg";
|
||||||
|
|
||||||
|
private QueueGui? _gui;
|
||||||
|
|
||||||
|
protected override void Startup()
|
||||||
|
{
|
||||||
|
_gui = new QueueGui();
|
||||||
|
_userInterfaceManager.StateRoot.AddChild(_gui);
|
||||||
|
|
||||||
|
_gui.QuitPressed += OnQuitPressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Shutdown()
|
||||||
|
{
|
||||||
|
_gui!.QuitPressed -= OnQuitPressed;
|
||||||
|
_gui.Dispose();
|
||||||
|
|
||||||
|
Ding();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Ding()
|
||||||
|
{
|
||||||
|
if (IoCManager.Resolve<IEntityManager>().TrySystem<AudioSystem>(out var audio))
|
||||||
|
{
|
||||||
|
audio.PlayGlobal(JoinSoundPath, Filter.Local(), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnQueueUpdate(MsgQueueUpdate msg)
|
||||||
|
{
|
||||||
|
_gui?.UpdateInfo(msg.Total, msg.Position);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnQuitPressed()
|
||||||
|
{
|
||||||
|
_consoleHost.ExecuteCommand("quit");
|
||||||
|
}
|
||||||
|
}
|
||||||
23
Content.Client/White/Sponsors/SponsorsManager.cs
Normal file
23
Content.Client/White/Sponsors/SponsorsManager.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using Content.Shared.White.Sponsors;
|
||||||
|
using Robust.Shared.Network;
|
||||||
|
|
||||||
|
namespace Content.Client.White.Sponsors;
|
||||||
|
|
||||||
|
public sealed class SponsorsManager
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IClientNetManager _netMgr = default!;
|
||||||
|
|
||||||
|
private SponsorInfo? _info;
|
||||||
|
|
||||||
|
public void Initialize()
|
||||||
|
{
|
||||||
|
_netMgr.RegisterNetMessage<MsgSponsorInfo>(msg => _info = msg.Info);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGetInfo([NotNullWhen(true)] out SponsorInfo? sponsor)
|
||||||
|
{
|
||||||
|
sponsor = _info;
|
||||||
|
return _info != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ using Content.Server.Administration.Managers;
|
|||||||
using Content.Server.Administration.Systems;
|
using Content.Server.Administration.Systems;
|
||||||
using Content.Server.MoMMI;
|
using Content.Server.MoMMI;
|
||||||
using Content.Server.Preferences.Managers;
|
using Content.Server.Preferences.Managers;
|
||||||
|
using Content.Server.White.Sponsors;
|
||||||
using Content.Shared.Administration;
|
using Content.Shared.Administration;
|
||||||
using Content.Shared.CCVar;
|
using Content.Shared.CCVar;
|
||||||
using Content.Shared.Chat;
|
using Content.Shared.Chat;
|
||||||
@@ -46,6 +47,10 @@ namespace Content.Server.Chat.Managers
|
|||||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||||
|
|
||||||
|
/// WD-EDIT
|
||||||
|
[Dependency] private readonly SponsorsManager _sponsorsManager = default!;
|
||||||
|
/// WD-EDIT
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The maximum length a player-sent message can be sent
|
/// The maximum length a player-sent message can be sent
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -69,7 +74,8 @@ namespace Content.Server.Chat.Managers
|
|||||||
|
|
||||||
private void OnOocEnabledChanged(bool val)
|
private void OnOocEnabledChanged(bool val)
|
||||||
{
|
{
|
||||||
if (_oocEnabled == val) return;
|
if (_oocEnabled == val)
|
||||||
|
return;
|
||||||
|
|
||||||
_oocEnabled = val;
|
_oocEnabled = val;
|
||||||
DispatchServerAnnouncement(Loc.GetString(val ? "chat-manager-ooc-chat-enabled-message" : "chat-manager-ooc-chat-disabled-message"));
|
DispatchServerAnnouncement(Loc.GetString(val ? "chat-manager-ooc-chat-enabled-message" : "chat-manager-ooc-chat-disabled-message"));
|
||||||
@@ -77,7 +83,8 @@ namespace Content.Server.Chat.Managers
|
|||||||
|
|
||||||
private void OnAdminOocEnabledChanged(bool val)
|
private void OnAdminOocEnabledChanged(bool val)
|
||||||
{
|
{
|
||||||
if (_adminOocEnabled == val) return;
|
if (_adminOocEnabled == val)
|
||||||
|
return;
|
||||||
|
|
||||||
_adminOocEnabled = val;
|
_adminOocEnabled = val;
|
||||||
DispatchServerAnnouncement(Loc.GetString(val ? "chat-manager-admin-ooc-chat-enabled-message" : "chat-manager-admin-ooc-chat-disabled-message"));
|
DispatchServerAnnouncement(Loc.GetString(val ? "chat-manager-admin-ooc-chat-enabled-message" : "chat-manager-admin-ooc-chat-disabled-message"));
|
||||||
@@ -119,7 +126,7 @@ namespace Content.Server.Chat.Managers
|
|||||||
public void DispatchServerMessage(ICommonSession player, string message, bool suppressLog = false)
|
public void DispatchServerMessage(ICommonSession player, string message, bool suppressLog = false)
|
||||||
{
|
{
|
||||||
var wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", FormattedMessage.EscapeText(message)));
|
var wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", FormattedMessage.EscapeText(message)));
|
||||||
ChatMessageToOne(ChatChannel.Server, message, wrappedMessage, default, false, player.ConnectedClient);
|
ChatMessageToOne(ChatChannel.Server, message, wrappedMessage, default, false, player.Channel);
|
||||||
|
|
||||||
if (!suppressLog)
|
if (!suppressLog)
|
||||||
_adminLogger.Add(LogType.Chat, LogImpact.Low, $"Server message to {player:Player}: {message}");
|
_adminLogger.Add(LogType.Chat, LogImpact.Low, $"Server message to {player:Player}: {message}");
|
||||||
@@ -127,7 +134,7 @@ namespace Content.Server.Chat.Managers
|
|||||||
|
|
||||||
public void SendAdminAnnouncement(string message)
|
public void SendAdminAnnouncement(string message)
|
||||||
{
|
{
|
||||||
var clients = _adminManager.ActiveAdmins.Select(p => p.ConnectedClient);
|
var clients = _adminManager.ActiveAdmins.Select(p => p.Channel);
|
||||||
|
|
||||||
var wrappedMessage = Loc.GetString("chat-manager-send-admin-announcement-wrap-message",
|
var wrappedMessage = Loc.GetString("chat-manager-send-admin-announcement-wrap-message",
|
||||||
("adminChannelName", Loc.GetString("chat-manager-admin-channel-name")), ("message", FormattedMessage.EscapeText(message)));
|
("adminChannelName", Loc.GetString("chat-manager-admin-channel-name")), ("message", FormattedMessage.EscapeText(message)));
|
||||||
@@ -138,7 +145,7 @@ namespace Content.Server.Chat.Managers
|
|||||||
|
|
||||||
public void SendAdminAlert(string message)
|
public void SendAdminAlert(string message)
|
||||||
{
|
{
|
||||||
var clients = _adminManager.ActiveAdmins.Select(p => p.ConnectedClient);
|
var clients = _adminManager.ActiveAdmins.Select(p => p.Channel);
|
||||||
|
|
||||||
var wrappedMessage = Loc.GetString("chat-manager-send-admin-announcement-wrap-message",
|
var wrappedMessage = Loc.GetString("chat-manager-send-admin-announcement-wrap-message",
|
||||||
("adminChannelName", Loc.GetString("chat-manager-admin-channel-name")), ("message", FormattedMessage.EscapeText(message)));
|
("adminChannelName", Loc.GetString("chat-manager-admin-channel-name")), ("message", FormattedMessage.EscapeText(message)));
|
||||||
@@ -149,7 +156,7 @@ namespace Content.Server.Chat.Managers
|
|||||||
public void SendAdminAlert(EntityUid player, string message)
|
public void SendAdminAlert(EntityUid player, string message)
|
||||||
{
|
{
|
||||||
var mindSystem = _entityManager.System<SharedMindSystem>();
|
var mindSystem = _entityManager.System<SharedMindSystem>();
|
||||||
if (!mindSystem.TryGetMind(player, out var mindId, out var mind))
|
if (!mindSystem.TryGetMind(player, out _, out var mind))
|
||||||
{
|
{
|
||||||
SendAdminAlert(message);
|
SendAdminAlert(message);
|
||||||
return;
|
return;
|
||||||
@@ -230,12 +237,19 @@ namespace Content.Server.Chat.Managers
|
|||||||
var prefs = _preferencesManager.GetPreferences(player.UserId);
|
var prefs = _preferencesManager.GetPreferences(player.UserId);
|
||||||
colorOverride = prefs.AdminOOCColor;
|
colorOverride = prefs.AdminOOCColor;
|
||||||
}
|
}
|
||||||
if (player.ConnectedClient.UserData.PatronTier is { } patron &&
|
if (player.Channel.UserData.PatronTier is { } patron &&
|
||||||
PatronOocColors.TryGetValue(patron, out var patronColor))
|
PatronOocColors.TryGetValue(patron, out var patronColor))
|
||||||
{
|
{
|
||||||
wrappedMessage = Loc.GetString("chat-manager-send-ooc-patron-wrap-message", ("patronColor", patronColor),("playerName", player.Name), ("message", FormattedMessage.EscapeText(message)));
|
wrappedMessage = Loc.GetString("chat-manager-send-ooc-patron-wrap-message", ("patronColor", patronColor),("playerName", player.Name), ("message", FormattedMessage.EscapeText(message)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//WD-EDIT
|
||||||
|
if (_sponsorsManager.TryGetInfo(player.UserId, out var sponsorData) && sponsorData.OOCColor != null)
|
||||||
|
{
|
||||||
|
wrappedMessage = Loc.GetString("chat-manager-send-ooc-patron-wrap-message", ("patronColor", sponsorData.OOCColor),("playerName", player.Name), ("message", FormattedMessage.EscapeText(message)));
|
||||||
|
}
|
||||||
|
//WD-EDIT
|
||||||
|
|
||||||
//TODO: player.Name color, this will need to change the structure of the MsgChatMessage
|
//TODO: player.Name color, this will need to change the structure of the MsgChatMessage
|
||||||
ChatMessageToAll(ChatChannel.OOC, message, wrappedMessage, EntityUid.Invalid, hideChat: false, recordReplay: true, colorOverride: colorOverride, author: player.UserId);
|
ChatMessageToAll(ChatChannel.OOC, message, wrappedMessage, EntityUid.Invalid, hideChat: false, recordReplay: true, colorOverride: colorOverride, author: player.UserId);
|
||||||
_mommiLink.SendOOCMessage(player.Name, message);
|
_mommiLink.SendOOCMessage(player.Name, message);
|
||||||
@@ -250,14 +264,14 @@ namespace Content.Server.Chat.Managers
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var clients = _adminManager.ActiveAdmins.Select(p => p.ConnectedClient);
|
var clients = _adminManager.ActiveAdmins.Select(p => p.Channel);
|
||||||
var wrappedMessage = Loc.GetString("chat-manager-send-admin-chat-wrap-message",
|
var wrappedMessage = Loc.GetString("chat-manager-send-admin-chat-wrap-message",
|
||||||
("adminChannelName", Loc.GetString("chat-manager-admin-channel-name")),
|
("adminChannelName", Loc.GetString("chat-manager-admin-channel-name")),
|
||||||
("playerName", player.Name), ("message", FormattedMessage.EscapeText(message)));
|
("playerName", player.Name), ("message", FormattedMessage.EscapeText(message)));
|
||||||
|
|
||||||
foreach (var client in clients)
|
foreach (var client in clients)
|
||||||
{
|
{
|
||||||
var isSource = client != player.ConnectedClient;
|
var isSource = client != player.Channel;
|
||||||
ChatMessageToOne(ChatChannel.AdminChat,
|
ChatMessageToOne(ChatChannel.AdminChat,
|
||||||
message,
|
message,
|
||||||
wrappedMessage,
|
wrappedMessage,
|
||||||
@@ -283,7 +297,7 @@ namespace Content.Server.Chat.Managers
|
|||||||
user?.AddEntity(netSource);
|
user?.AddEntity(netSource);
|
||||||
|
|
||||||
var msg = new ChatMessage(channel, message, wrappedMessage, netSource, user?.Key, hideChat, colorOverride, audioPath, audioVolume);
|
var msg = new ChatMessage(channel, message, wrappedMessage, netSource, user?.Key, hideChat, colorOverride, audioPath, audioVolume);
|
||||||
_netManager.ServerSendMessage(new MsgChatMessage() { Message = msg }, client);
|
_netManager.ServerSendMessage(new MsgChatMessage { Message = msg }, client);
|
||||||
|
|
||||||
if (!recordReplay)
|
if (!recordReplay)
|
||||||
return;
|
return;
|
||||||
@@ -296,7 +310,10 @@ namespace Content.Server.Chat.Managers
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void ChatMessageToMany(ChatChannel channel, string message, string wrappedMessage, EntityUid source, bool hideChat, bool recordReplay, IEnumerable<INetChannel> clients, Color? colorOverride = null, string? audioPath = null, float audioVolume = 0, NetUserId? author = null)
|
public void ChatMessageToMany(ChatChannel channel, string message, string wrappedMessage, EntityUid source, bool hideChat, bool recordReplay, IEnumerable<INetChannel> clients, Color? colorOverride = null, string? audioPath = null, float audioVolume = 0, NetUserId? author = null)
|
||||||
=> ChatMessageToMany(channel, message, wrappedMessage, source, hideChat, recordReplay, clients.ToList(), colorOverride, audioPath, audioVolume, author);
|
{
|
||||||
|
ChatMessageToMany(channel, message, wrappedMessage, source, hideChat, recordReplay, clients.ToList(),
|
||||||
|
colorOverride, audioPath, audioVolume, author);
|
||||||
|
}
|
||||||
|
|
||||||
public void ChatMessageToMany(ChatChannel channel, string message, string wrappedMessage, EntityUid source, bool hideChat, bool recordReplay, List<INetChannel> clients, Color? colorOverride = null, string? audioPath = null, float audioVolume = 0, NetUserId? author = null)
|
public void ChatMessageToMany(ChatChannel channel, string message, string wrappedMessage, EntityUid source, bool hideChat, bool recordReplay, List<INetChannel> clients, Color? colorOverride = null, string? audioPath = null, float audioVolume = 0, NetUserId? author = null)
|
||||||
{
|
{
|
||||||
@@ -305,7 +322,7 @@ namespace Content.Server.Chat.Managers
|
|||||||
user?.AddEntity(netSource);
|
user?.AddEntity(netSource);
|
||||||
|
|
||||||
var msg = new ChatMessage(channel, message, wrappedMessage, netSource, user?.Key, hideChat, colorOverride, audioPath, audioVolume);
|
var msg = new ChatMessage(channel, message, wrappedMessage, netSource, user?.Key, hideChat, colorOverride, audioPath, audioVolume);
|
||||||
_netManager.ServerSendToMany(new MsgChatMessage() { Message = msg }, clients);
|
_netManager.ServerSendToMany(new MsgChatMessage { Message = msg }, clients);
|
||||||
|
|
||||||
if (!recordReplay)
|
if (!recordReplay)
|
||||||
return;
|
return;
|
||||||
@@ -317,8 +334,17 @@ namespace Content.Server.Chat.Managers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ChatMessageToManyFiltered(Filter filter, ChatChannel channel, string message, string wrappedMessage, EntityUid source,
|
public void ChatMessageToManyFiltered(
|
||||||
bool hideChat, bool recordReplay, Color? colorOverride = null, string? audioPath = null, float audioVolume = 0)
|
Filter filter,
|
||||||
|
ChatChannel channel,
|
||||||
|
string message,
|
||||||
|
string wrappedMessage,
|
||||||
|
EntityUid source,
|
||||||
|
bool hideChat,
|
||||||
|
bool recordReplay,
|
||||||
|
Color? colorOverride = null,
|
||||||
|
string? audioPath = null,
|
||||||
|
float audioVolume = 0)
|
||||||
{
|
{
|
||||||
if (!recordReplay && !filter.Recipients.Any())
|
if (!recordReplay && !filter.Recipients.Any())
|
||||||
return;
|
return;
|
||||||
@@ -326,7 +352,7 @@ namespace Content.Server.Chat.Managers
|
|||||||
var clients = new List<INetChannel>();
|
var clients = new List<INetChannel>();
|
||||||
foreach (var recipient in filter.Recipients)
|
foreach (var recipient in filter.Recipients)
|
||||||
{
|
{
|
||||||
clients.Add(recipient.ConnectedClient);
|
clients.Add(recipient.Channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
ChatMessageToMany(channel, message, wrappedMessage, source, hideChat, recordReplay, clients, colorOverride, audioPath, audioVolume);
|
ChatMessageToMany(channel, message, wrappedMessage, source, hideChat, recordReplay, clients, colorOverride, audioPath, audioVolume);
|
||||||
@@ -339,7 +365,7 @@ namespace Content.Server.Chat.Managers
|
|||||||
user?.AddEntity(netSource);
|
user?.AddEntity(netSource);
|
||||||
|
|
||||||
var msg = new ChatMessage(channel, message, wrappedMessage, netSource, user?.Key, hideChat, colorOverride, audioPath, audioVolume);
|
var msg = new ChatMessage(channel, message, wrappedMessage, netSource, user?.Key, hideChat, colorOverride, audioPath, audioVolume);
|
||||||
_netManager.ServerSendToAll(new MsgChatMessage() { Message = msg });
|
_netManager.ServerSendToAll(new MsgChatMessage { Message = msg });
|
||||||
|
|
||||||
if (!recordReplay)
|
if (!recordReplay)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -3,9 +3,11 @@ using System.Threading.Tasks;
|
|||||||
using Content.Server.Database;
|
using Content.Server.Database;
|
||||||
using Content.Server.GameTicking;
|
using Content.Server.GameTicking;
|
||||||
using Content.Server.Preferences.Managers;
|
using Content.Server.Preferences.Managers;
|
||||||
|
using Content.Server.White.Sponsors;
|
||||||
using Content.Shared.CCVar;
|
using Content.Shared.CCVar;
|
||||||
using Content.Shared.GameTicking;
|
using Content.Shared.GameTicking;
|
||||||
using Content.Shared.Players.PlayTimeTracking;
|
using Content.Shared.Players.PlayTimeTracking;
|
||||||
|
using Content.Shared.White;
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
using Robust.Shared.Configuration;
|
using Robust.Shared.Configuration;
|
||||||
using Robust.Shared.Network;
|
using Robust.Shared.Network;
|
||||||
@@ -16,6 +18,7 @@ namespace Content.Server.Connection
|
|||||||
public interface IConnectionManager
|
public interface IConnectionManager
|
||||||
{
|
{
|
||||||
void Initialize();
|
void Initialize();
|
||||||
|
Task<bool> HavePrivilegedJoin(NetUserId userId); // WD-EDIT
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -31,6 +34,10 @@ namespace Content.Server.Connection
|
|||||||
[Dependency] private readonly ILocalizationManager _loc = default!;
|
[Dependency] private readonly ILocalizationManager _loc = default!;
|
||||||
[Dependency] private readonly ServerDbEntryManager _serverDbEntry = default!;
|
[Dependency] private readonly ServerDbEntryManager _serverDbEntry = default!;
|
||||||
|
|
||||||
|
//WD-EDIT
|
||||||
|
[Dependency] private readonly SponsorsManager _sponsorsManager = default!;
|
||||||
|
//WD-EDIT
|
||||||
|
|
||||||
public void Initialize()
|
public void Initialize()
|
||||||
{
|
{
|
||||||
_netMgr.Connecting += NetMgrOnConnecting;
|
_netMgr.Connecting += NetMgrOnConnecting;
|
||||||
@@ -152,13 +159,14 @@ namespace Content.Server.Connection
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var wasInGame = EntitySystem.TryGet<GameTicker>(out var ticker) &&
|
//WD-EDIT
|
||||||
ticker.PlayerGameStatuses.TryGetValue(userId, out var status) &&
|
var isQueueEnabled = _cfg.GetCVar(WhiteCVars.QueueEnabled);
|
||||||
status == PlayerGameStatus.JoinedGame;
|
var isPrivileged = await HavePrivilegedJoin(e.UserId);
|
||||||
if ((_plyMgr.PlayerCount >= _cfg.GetCVar(CCVars.SoftMaxPlayers) && adminData is null) && !wasInGame)
|
if (_plyMgr.PlayerCount >= _cfg.GetCVar(CCVars.SoftMaxPlayers) && !isPrivileged && !isQueueEnabled)
|
||||||
{
|
{
|
||||||
return (ConnectionDenyReason.Full, Loc.GetString("soft-player-cap-full"), null);
|
return (ConnectionDenyReason.Full, Loc.GetString("soft-player-cap-full"), null);
|
||||||
}
|
}
|
||||||
|
//WD-EDIT
|
||||||
|
|
||||||
var bans = await _db.GetServerBansAsync(addr, userId, hwId, includeUnbanned: false);
|
var bans = await _db.GetServerBansAsync(addr, userId, hwId, includeUnbanned: false);
|
||||||
if (bans.Count > 0)
|
if (bans.Count > 0)
|
||||||
@@ -205,5 +213,20 @@ namespace Content.Server.Connection
|
|||||||
await _db.AssignUserIdAsync(name, assigned);
|
await _db.AssignUserIdAsync(name, assigned);
|
||||||
return assigned;
|
return assigned;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//WD-EDIT
|
||||||
|
public async Task<bool> HavePrivilegedJoin(NetUserId userId)
|
||||||
|
{
|
||||||
|
var adminData = await _dbManager.GetAdminDataForAsync(userId);
|
||||||
|
|
||||||
|
var havePriorityJoin = _sponsorsManager.TryGetInfo(userId, out var sponsorData) && sponsorData.HavePriorityJoin;
|
||||||
|
var wasInGame = EntitySystem.TryGet<GameTicker>(out var ticker) &&
|
||||||
|
ticker.PlayerGameStatuses.TryGetValue(userId, out var status) &&
|
||||||
|
status == PlayerGameStatus.JoinedGame;
|
||||||
|
return adminData != null ||
|
||||||
|
havePriorityJoin ||
|
||||||
|
wasInGame;
|
||||||
|
}
|
||||||
|
//WD-EDIT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ using Robust.Shared.ContentPack;
|
|||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
|
using Content.Server.White.JoinQueue;
|
||||||
|
using Content.Server.White.Sponsors;
|
||||||
|
|
||||||
namespace Content.Server.Entry
|
namespace Content.Server.Entry
|
||||||
{
|
{
|
||||||
@@ -41,7 +43,6 @@ namespace Content.Server.Entry
|
|||||||
private IVoteManager _voteManager = default!;
|
private IVoteManager _voteManager = default!;
|
||||||
private ServerUpdateManager _updateManager = default!;
|
private ServerUpdateManager _updateManager = default!;
|
||||||
private PlayTimeTrackingManager? _playTimeTracking;
|
private PlayTimeTrackingManager? _playTimeTracking;
|
||||||
private IEntitySystemManager? _sysMan;
|
|
||||||
private IServerDbManager? _dbManager;
|
private IServerDbManager? _dbManager;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -82,13 +83,14 @@ namespace Content.Server.Entry
|
|||||||
var configManager = IoCManager.Resolve<IConfigurationManager>();
|
var configManager = IoCManager.Resolve<IConfigurationManager>();
|
||||||
var dest = configManager.GetCVar(CCVars.DestinationFile);
|
var dest = configManager.GetCVar(CCVars.DestinationFile);
|
||||||
IoCManager.Resolve<ContentLocalizationManager>().Initialize();
|
IoCManager.Resolve<ContentLocalizationManager>().Initialize();
|
||||||
if (string.IsNullOrEmpty(dest)) //hacky but it keeps load times for the generator down.
|
if (!string.IsNullOrEmpty(dest)) //hacky but it keeps load times for the generator down.
|
||||||
{
|
return;
|
||||||
|
|
||||||
_euiManager = IoCManager.Resolve<EuiManager>();
|
_euiManager = IoCManager.Resolve<EuiManager>();
|
||||||
_voteManager = IoCManager.Resolve<IVoteManager>();
|
_voteManager = IoCManager.Resolve<IVoteManager>();
|
||||||
_updateManager = IoCManager.Resolve<ServerUpdateManager>();
|
_updateManager = IoCManager.Resolve<ServerUpdateManager>();
|
||||||
_playTimeTracking = IoCManager.Resolve<PlayTimeTrackingManager>();
|
_playTimeTracking = IoCManager.Resolve<PlayTimeTrackingManager>();
|
||||||
_sysMan = IoCManager.Resolve<IEntitySystemManager>();
|
IoCManager.Resolve<IEntitySystemManager>();
|
||||||
_dbManager = IoCManager.Resolve<IServerDbManager>();
|
_dbManager = IoCManager.Resolve<IServerDbManager>();
|
||||||
|
|
||||||
logManager.GetSawmill("Storage").Level = LogLevel.Info;
|
logManager.GetSawmill("Storage").Level = LogLevel.Info;
|
||||||
@@ -103,11 +105,15 @@ namespace Content.Server.Entry
|
|||||||
IoCManager.Resolve<GhostKickManager>().Initialize();
|
IoCManager.Resolve<GhostKickManager>().Initialize();
|
||||||
IoCManager.Resolve<ServerInfoManager>().Initialize();
|
IoCManager.Resolve<ServerInfoManager>().Initialize();
|
||||||
|
|
||||||
|
//WD-EDIT
|
||||||
|
IoCManager.Resolve<SponsorsManager>().Initialize();
|
||||||
|
IoCManager.Resolve<JoinQueueManager>().Initialize();
|
||||||
|
//WD-EDIT
|
||||||
|
|
||||||
_voteManager.Initialize();
|
_voteManager.Initialize();
|
||||||
_updateManager.Initialize();
|
_updateManager.Initialize();
|
||||||
_playTimeTracking.Initialize();
|
_playTimeTracking.Initialize();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public override void PostInit()
|
public override void PostInit()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ using JetBrains.Annotations;
|
|||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
using Robust.Shared.Enums;
|
using Robust.Shared.Enums;
|
||||||
using Robust.Shared.Player;
|
using Robust.Shared.Player;
|
||||||
using Robust.Shared.Timing;
|
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
namespace Content.Server.GameTicking
|
namespace Content.Server.GameTicking
|
||||||
@@ -32,7 +31,7 @@ namespace Content.Server.GameTicking
|
|||||||
if (args.NewStatus != SessionStatus.Disconnected)
|
if (args.NewStatus != SessionStatus.Disconnected)
|
||||||
{
|
{
|
||||||
mind.Session = session;
|
mind.Session = session;
|
||||||
_pvsOverride.AddSessionOverride(GetNetEntity(mindId.Value), session);
|
_pvsOverride.AddSessionOverride(mindId.Value, session);
|
||||||
}
|
}
|
||||||
|
|
||||||
DebugTools.Assert(mind.Session == session);
|
DebugTools.Assert(mind.Session == session);
|
||||||
@@ -56,7 +55,7 @@ namespace Content.Server.GameTicking
|
|||||||
|
|
||||||
// Make the player actually join the game.
|
// Make the player actually join the game.
|
||||||
// timer time must be > tick length
|
// timer time must be > tick length
|
||||||
Timer.Spawn(0, () => _playerManager.JoinGame(args.Session));
|
// Timer.Spawn(0, args.Session.JoinGame); // Moved to `JoinQueueManager`(WD-EDIT)
|
||||||
|
|
||||||
var record = await _dbManager.GetPlayerRecordByUserId(args.Session.UserId);
|
var record = await _dbManager.GetPlayerRecordByUserId(args.Session.UserId);
|
||||||
var firstConnection = record != null &&
|
var firstConnection = record != null &&
|
||||||
@@ -124,6 +123,7 @@ namespace Content.Server.GameTicking
|
|||||||
mind.Session = null;
|
mind.Session = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_playerGameStatuses.ContainsKey(args.Session.UserId)) //WD-EDIT
|
||||||
_userDb.ClientDisconnected(session);
|
_userDb.ClientDisconnected(session);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -166,7 +166,7 @@ namespace Content.Server.GameTicking
|
|||||||
_playerGameStatuses[session.UserId] = PlayerGameStatus.JoinedGame;
|
_playerGameStatuses[session.UserId] = PlayerGameStatus.JoinedGame;
|
||||||
_db.AddRoundPlayers(RoundId, session.UserId);
|
_db.AddRoundPlayers(RoundId, session.UserId);
|
||||||
|
|
||||||
RaiseNetworkEvent(new TickerJoinGameEvent(), session.ConnectedClient);
|
RaiseNetworkEvent(new TickerJoinGameEvent(), session.Channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PlayerJoinLobby(ICommonSession session)
|
private void PlayerJoinLobby(ICommonSession session)
|
||||||
@@ -174,7 +174,7 @@ namespace Content.Server.GameTicking
|
|||||||
_playerGameStatuses[session.UserId] = LobbyEnabled ? PlayerGameStatus.NotReadyToPlay : PlayerGameStatus.ReadyToPlay;
|
_playerGameStatuses[session.UserId] = LobbyEnabled ? PlayerGameStatus.NotReadyToPlay : PlayerGameStatus.ReadyToPlay;
|
||||||
_db.AddRoundPlayers(RoundId, session.UserId);
|
_db.AddRoundPlayers(RoundId, session.UserId);
|
||||||
|
|
||||||
var client = session.ConnectedClient;
|
var client = session.Channel;
|
||||||
RaiseNetworkEvent(new TickerJoinLobbyEvent(), client);
|
RaiseNetworkEvent(new TickerJoinLobbyEvent(), client);
|
||||||
RaiseNetworkEvent(GetStatusMsg(session), client);
|
RaiseNetworkEvent(GetStatusMsg(session), client);
|
||||||
RaiseNetworkEvent(GetInfoMsg(), client);
|
RaiseNetworkEvent(GetInfoMsg(), client);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Text.Json.Nodes;
|
using System.Text.Json.Nodes;
|
||||||
|
using Content.Server.White.JoinQueue;
|
||||||
using Content.Shared.CCVar;
|
using Content.Shared.CCVar;
|
||||||
using Content.Shared.GameTicking;
|
using Content.Shared.GameTicking;
|
||||||
using Robust.Server.ServerStatus;
|
using Robust.Server.ServerStatus;
|
||||||
@@ -28,6 +29,10 @@ namespace Content.Server.GameTicking
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[Dependency] private readonly SharedGameTicker _gameTicker = default!;
|
[Dependency] private readonly SharedGameTicker _gameTicker = default!;
|
||||||
|
|
||||||
|
// WD-EDIT
|
||||||
|
[Dependency] private readonly JoinQueueManager _queueManager = default!;
|
||||||
|
// WD-EDIT
|
||||||
|
|
||||||
private void InitializeStatusShell()
|
private void InitializeStatusShell()
|
||||||
{
|
{
|
||||||
IoCManager.Resolve<IStatusHost>().OnStatusRequest += GetStatusResponse;
|
IoCManager.Resolve<IStatusHost>().OnStatusRequest += GetStatusResponse;
|
||||||
@@ -43,7 +48,7 @@ namespace Content.Server.GameTicking
|
|||||||
jObject["name"] = _baseServer.ServerName;
|
jObject["name"] = _baseServer.ServerName;
|
||||||
jObject["map"] = _gameMapManager.GetSelectedMap()?.MapName;
|
jObject["map"] = _gameMapManager.GetSelectedMap()?.MapName;
|
||||||
jObject["round_id"] = _gameTicker.RoundId;
|
jObject["round_id"] = _gameTicker.RoundId;
|
||||||
jObject["players"] = _playerManager.PlayerCount;
|
jObject["players"] = _queueManager.ActualPlayersCount; //WD-EDIT
|
||||||
jObject["soft_max_players"] = _cfg.GetCVar(CCVars.SoftMaxPlayers);
|
jObject["soft_max_players"] = _cfg.GetCVar(CCVars.SoftMaxPlayers);
|
||||||
jObject["panic_bunker"] = _cfg.GetCVar(CCVars.PanicBunkerEnabled);
|
jObject["panic_bunker"] = _cfg.GetCVar(CCVars.PanicBunkerEnabled);
|
||||||
jObject["run_level"] = (int) _runLevel;
|
jObject["run_level"] = (int) _runLevel;
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ using Content.Server.ServerInfo;
|
|||||||
using Content.Server.ServerUpdates;
|
using Content.Server.ServerUpdates;
|
||||||
using Content.Server.Voting.Managers;
|
using Content.Server.Voting.Managers;
|
||||||
using Content.Server.Worldgen.Tools;
|
using Content.Server.Worldgen.Tools;
|
||||||
|
using Content.Server.White.JoinQueue;
|
||||||
|
using Content.Server.White.Sponsors;
|
||||||
using Content.Shared.Administration.Logs;
|
using Content.Shared.Administration.Logs;
|
||||||
using Content.Shared.Administration.Managers;
|
using Content.Shared.Administration.Managers;
|
||||||
using Content.Shared.Kitchen;
|
using Content.Shared.Kitchen;
|
||||||
@@ -58,6 +60,11 @@ namespace Content.Server.IoC
|
|||||||
IoCManager.Register<PoissonDiskSampler>();
|
IoCManager.Register<PoissonDiskSampler>();
|
||||||
IoCManager.Register<DiscordWebhook>();
|
IoCManager.Register<DiscordWebhook>();
|
||||||
IoCManager.Register<ServerDbEntryManager>();
|
IoCManager.Register<ServerDbEntryManager>();
|
||||||
|
|
||||||
|
// WD-EDIT
|
||||||
|
IoCManager.Register<SponsorsManager>();
|
||||||
|
IoCManager.Register<JoinQueueManager>();
|
||||||
|
// WD-EDIT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using System.Threading;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Content.Server.Database;
|
using Content.Server.Database;
|
||||||
using Content.Server.Humanoid;
|
using Content.Server.Humanoid;
|
||||||
|
using Content.Server.White.Sponsors;
|
||||||
using Content.Shared.CCVar;
|
using Content.Shared.CCVar;
|
||||||
using Content.Shared.Humanoid.Prototypes;
|
using Content.Shared.Humanoid.Prototypes;
|
||||||
using Content.Shared.Preferences;
|
using Content.Shared.Preferences;
|
||||||
@@ -27,6 +28,10 @@ namespace Content.Server.Preferences.Managers
|
|||||||
[Dependency] private readonly IServerDbManager _db = default!;
|
[Dependency] private readonly IServerDbManager _db = default!;
|
||||||
[Dependency] private readonly IPrototypeManager _protos = default!;
|
[Dependency] private readonly IPrototypeManager _protos = default!;
|
||||||
|
|
||||||
|
// WD-EDIT
|
||||||
|
[Dependency] private readonly SponsorsManager _sponsors = default!;
|
||||||
|
// WD-EDIT
|
||||||
|
|
||||||
// Cache player prefs on the server so we don't need as much async hell related to them.
|
// Cache player prefs on the server so we don't need as much async hell related to them.
|
||||||
private readonly Dictionary<NetUserId, PlayerPrefData> _cachedPlayerPrefs =
|
private readonly Dictionary<NetUserId, PlayerPrefData> _cachedPlayerPrefs =
|
||||||
new();
|
new();
|
||||||
@@ -99,7 +104,10 @@ namespace Content.Server.Preferences.Managers
|
|||||||
|
|
||||||
var curPrefs = prefsData.Prefs!;
|
var curPrefs = prefsData.Prefs!;
|
||||||
|
|
||||||
profile.EnsureValid();
|
// WD-EDIT
|
||||||
|
var allowedMarkings = _sponsors.TryGetInfo(message.MsgChannel.UserId, out var sponsor) ? sponsor.AllowedMarkings : new string[]{};
|
||||||
|
profile.EnsureValid(allowedMarkings);
|
||||||
|
// WD-EDIT
|
||||||
|
|
||||||
var profiles = new Dictionary<int, ICharacterProfile>(curPrefs.Characters)
|
var profiles = new Dictionary<int, ICharacterProfile>(curPrefs.Characters)
|
||||||
{
|
{
|
||||||
@@ -193,6 +201,15 @@ namespace Content.Server.Preferences.Managers
|
|||||||
async Task LoadPrefs()
|
async Task LoadPrefs()
|
||||||
{
|
{
|
||||||
var prefs = await GetOrCreatePreferencesAsync(session.UserId);
|
var prefs = await GetOrCreatePreferencesAsync(session.UserId);
|
||||||
|
|
||||||
|
// WD-EDIT
|
||||||
|
foreach (var (_, profile) in prefs.Characters)
|
||||||
|
{
|
||||||
|
var allowedMarkings = _sponsors.TryGetInfo(session.UserId, out var sponsor) ? sponsor.AllowedMarkings : new string[]{};
|
||||||
|
profile.EnsureValid(allowedMarkings);
|
||||||
|
}
|
||||||
|
// WD-EDIT
|
||||||
|
|
||||||
prefsData.Prefs = prefs;
|
prefsData.Prefs = prefs;
|
||||||
prefsData.PrefsLoaded = true;
|
prefsData.PrefsLoaded = true;
|
||||||
|
|
||||||
|
|||||||
132
Content.Server/White/JoinQueue/JoinQueueManager.cs
Normal file
132
Content.Server/White/JoinQueue/JoinQueueManager.cs
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using Content.Server.Connection;
|
||||||
|
using Content.Shared.CCVar;
|
||||||
|
using Content.Shared.White;
|
||||||
|
using Content.Shared.White.JoinQueue;
|
||||||
|
using Robust.Server.Player;
|
||||||
|
using Robust.Shared.Configuration;
|
||||||
|
using Robust.Shared.Enums;
|
||||||
|
using Robust.Shared.Network;
|
||||||
|
using Robust.Shared.Player;
|
||||||
|
using Robust.Shared.Timing;
|
||||||
|
|
||||||
|
namespace Content.Server.White.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
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||||
|
[Dependency] private readonly IConnectionManager _connectionManager = default!;
|
||||||
|
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||||
|
[Dependency] private readonly IServerNetManager _netManager = default!;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queue of active player sessions
|
||||||
|
/// </summary>
|
||||||
|
private readonly List<ICommonSession> _queue = new(); // Real Queue class can't delete disconnected users
|
||||||
|
|
||||||
|
private bool _isEnabled;
|
||||||
|
|
||||||
|
public int PlayerInQueueCount => _queue.Count;
|
||||||
|
public int ActualPlayersCount => _playerManager.PlayerCount - PlayerInQueueCount; // Now it's only real value with actual players count that in game
|
||||||
|
|
||||||
|
public void Initialize()
|
||||||
|
{
|
||||||
|
_netManager.RegisterNetMessage<MsgQueueUpdate>();
|
||||||
|
|
||||||
|
_cfg.OnValueChanged(WhiteCVars.QueueEnabled, OnQueueCVarChanged, true);
|
||||||
|
_playerManager.PlayerStatusChanged += OnPlayerStatusChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnQueueCVarChanged(bool value)
|
||||||
|
{
|
||||||
|
_isEnabled = value;
|
||||||
|
|
||||||
|
if (value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var session in _queue)
|
||||||
|
{
|
||||||
|
session.Channel.Disconnect("Queue was disabled");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void OnPlayerStatusChanged(object? sender, SessionStatusEventArgs e)
|
||||||
|
{
|
||||||
|
switch (e.NewStatus)
|
||||||
|
{
|
||||||
|
case SessionStatus.Connected:
|
||||||
|
{
|
||||||
|
if (!_isEnabled)
|
||||||
|
{
|
||||||
|
SendToGame(e.Session);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var isPrivileged = await _connectionManager.HavePrivilegedJoin(e.Session.UserId);
|
||||||
|
var haveFreeSlot = _playerManager.PlayerCount < _cfg.GetCVar(CCVars.SoftMaxPlayers);
|
||||||
|
if (isPrivileged || haveFreeSlot)
|
||||||
|
{
|
||||||
|
SendToGame(e.Session);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_queue.Add(e.Session);
|
||||||
|
ProcessQueue(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SessionStatus.Disconnected:
|
||||||
|
{
|
||||||
|
_queue.Remove(e.Session);
|
||||||
|
ProcessQueue(true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If possible, takes the first player in the queue and sends him into the game
|
||||||
|
/// </summary>
|
||||||
|
private void ProcessQueue(bool isDisconnect)
|
||||||
|
{
|
||||||
|
var players = ActualPlayersCount;
|
||||||
|
if (isDisconnect)
|
||||||
|
players--; // Decrease currently disconnected session but that has not yet been deleted
|
||||||
|
|
||||||
|
var haveFreeSlot = players < _cfg.GetCVar(CCVars.SoftMaxPlayers);
|
||||||
|
var queueContains = _queue.Count > 0;
|
||||||
|
if ((!_isEnabled || haveFreeSlot) && queueContains)
|
||||||
|
{
|
||||||
|
var session = _queue.First();
|
||||||
|
_queue.Remove(session);
|
||||||
|
SendToGame(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
SendUpdateMessages();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sends messages to all players in the queue with the current state of the queue
|
||||||
|
/// </summary>
|
||||||
|
private void SendUpdateMessages()
|
||||||
|
{
|
||||||
|
for (var i = 0; i < _queue.Count; i++)
|
||||||
|
{
|
||||||
|
_queue[i].Channel.SendMessage(new MsgQueueUpdate
|
||||||
|
{
|
||||||
|
Total = _queue.Count,
|
||||||
|
Position = i + 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Letting player's session into game, change player state
|
||||||
|
/// </summary>
|
||||||
|
private void SendToGame(ICommonSession s)
|
||||||
|
{
|
||||||
|
Timer.Spawn(0, () => _playerManager.JoinGame(s));
|
||||||
|
}
|
||||||
|
}
|
||||||
92
Content.Server/White/Sponsors/SponsorsManager.cs
Normal file
92
Content.Server/White/Sponsors/SponsorsManager.cs
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Net.Http.Json;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Content.Shared.CCVar;
|
||||||
|
using Content.Shared.White;
|
||||||
|
using Content.Shared.White.Sponsors;
|
||||||
|
using Robust.Shared.Configuration;
|
||||||
|
using Robust.Shared.Network;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
|
namespace Content.Server.White.Sponsors;
|
||||||
|
|
||||||
|
public sealed class SponsorsManager
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IServerNetManager _netMgr = default!;
|
||||||
|
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||||
|
|
||||||
|
private readonly HttpClient _httpClient = new();
|
||||||
|
|
||||||
|
private ISawmill _sawmill = default!;
|
||||||
|
private string _apiUrl = string.Empty;
|
||||||
|
|
||||||
|
private readonly Dictionary<NetUserId, SponsorInfo> _cachedSponsors = new();
|
||||||
|
|
||||||
|
public void Initialize()
|
||||||
|
{
|
||||||
|
_sawmill = Logger.GetSawmill("sponsors");
|
||||||
|
_cfg.OnValueChanged(WhiteCVars.SponsorsApiUrl, s => _apiUrl = s, true);
|
||||||
|
|
||||||
|
_netMgr.RegisterNetMessage<MsgSponsorInfo>();
|
||||||
|
|
||||||
|
_netMgr.Connecting += OnConnecting;
|
||||||
|
_netMgr.Connected += OnConnected;
|
||||||
|
_netMgr.Disconnect += OnDisconnect;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGetInfo(NetUserId userId, [NotNullWhen(true)] out SponsorInfo? sponsor)
|
||||||
|
{
|
||||||
|
return _cachedSponsors.TryGetValue(userId, out sponsor);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task OnConnecting(NetConnectingArgs e)
|
||||||
|
{
|
||||||
|
var info = await LoadSponsorInfo(e.UserId);
|
||||||
|
if (info?.Tier == null)
|
||||||
|
{
|
||||||
|
_cachedSponsors.Remove(e.UserId); // Remove from cache if sponsor expired
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DebugTools.Assert(!_cachedSponsors.ContainsKey(e.UserId), "Cached data was found on client connect");
|
||||||
|
|
||||||
|
_cachedSponsors[e.UserId] = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnConnected(object? sender, NetChannelArgs e)
|
||||||
|
{
|
||||||
|
var info = _cachedSponsors.TryGetValue(e.Channel.UserId, out var sponsor) ? sponsor : null;
|
||||||
|
var msg = new MsgSponsorInfo() { Info = info };
|
||||||
|
_netMgr.ServerSendMessage(msg, e.Channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDisconnect(object? sender, NetDisconnectedArgs e)
|
||||||
|
{
|
||||||
|
_cachedSponsors.Remove(e.Channel.UserId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<SponsorInfo?> LoadSponsorInfo(NetUserId userId)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(_apiUrl))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var url = $"{_apiUrl}/sponsors/{userId.ToString()}";
|
||||||
|
var response = await _httpClient.GetAsync(url);
|
||||||
|
if (response.StatusCode == HttpStatusCode.NotFound)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (response.StatusCode != HttpStatusCode.OK)
|
||||||
|
{
|
||||||
|
var errorText = await response.Content.ReadAsStringAsync();
|
||||||
|
_sawmill.Error(
|
||||||
|
"Failed to get player sponsor OOC color from API: [{StatusCode}] {Response}",
|
||||||
|
response.StatusCode,
|
||||||
|
errorText);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return await response.Content.ReadFromJsonAsync<SponsorInfo>();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -188,7 +188,7 @@ namespace Content.Shared.Humanoid
|
|||||||
return new(color.RByte, color.GByte, color.BByte);
|
return new(color.RByte, color.GByte, color.BByte);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static HumanoidCharacterAppearance EnsureValid(HumanoidCharacterAppearance appearance, string species, Sex sex)
|
public static HumanoidCharacterAppearance EnsureValid(HumanoidCharacterAppearance appearance, string species, string[] sponsorMarkings) //WD-EDIT
|
||||||
{
|
{
|
||||||
var hairStyleId = appearance.HairStyleId;
|
var hairStyleId = appearance.HairStyleId;
|
||||||
var facialHairStyleId = appearance.FacialHairStyleId;
|
var facialHairStyleId = appearance.FacialHairStyleId;
|
||||||
@@ -205,15 +205,43 @@ namespace Content.Shared.Humanoid
|
|||||||
hairStyleId = HairStyles.DefaultHairStyle;
|
hairStyleId = HairStyles.DefaultHairStyle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WD-EDIT
|
||||||
|
if (proto.TryIndex(hairStyleId, out MarkingPrototype? hairProto) &&
|
||||||
|
hairProto.SponsorOnly &&
|
||||||
|
!sponsorMarkings.Contains(hairStyleId))
|
||||||
|
{
|
||||||
|
hairStyleId = HairStyles.DefaultHairStyle;
|
||||||
|
}
|
||||||
|
// WD-EDIT
|
||||||
|
|
||||||
if (!markingManager.MarkingsByCategory(MarkingCategories.FacialHair).ContainsKey(facialHairStyleId))
|
if (!markingManager.MarkingsByCategory(MarkingCategories.FacialHair).ContainsKey(facialHairStyleId))
|
||||||
{
|
{
|
||||||
facialHairStyleId = HairStyles.DefaultFacialHairStyle;
|
facialHairStyleId = HairStyles.DefaultFacialHairStyle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WD-EDIT
|
||||||
|
if (proto.TryIndex(facialHairStyleId, out MarkingPrototype? facialHairProto) &&
|
||||||
|
facialHairProto.SponsorOnly &&
|
||||||
|
!sponsorMarkings.Contains(facialHairStyleId))
|
||||||
|
{
|
||||||
|
facialHairStyleId = HairStyles.DefaultFacialHairStyle;
|
||||||
|
}
|
||||||
|
// WD-EDIT
|
||||||
|
|
||||||
var markingSet = new MarkingSet();
|
var markingSet = new MarkingSet();
|
||||||
var skinColor = appearance.SkinColor;
|
var skinColor = appearance.SkinColor;
|
||||||
if (proto.TryIndex(species, out SpeciesPrototype? speciesProto))
|
if (!proto.TryIndex(species, out SpeciesPrototype? speciesProto))
|
||||||
{
|
{
|
||||||
|
return new HumanoidCharacterAppearance(
|
||||||
|
hairStyleId,
|
||||||
|
hairColor,
|
||||||
|
facialHairStyleId,
|
||||||
|
facialHairColor,
|
||||||
|
eyeColor,
|
||||||
|
skinColor,
|
||||||
|
markingSet.GetForwardEnumerator().ToList());
|
||||||
|
}
|
||||||
|
|
||||||
markingSet = new MarkingSet(appearance.Markings, speciesProto.MarkingPoints, markingManager, proto);
|
markingSet = new MarkingSet(appearance.Markings, speciesProto.MarkingPoints, markingManager, proto);
|
||||||
markingSet.EnsureValid(markingManager);
|
markingSet.EnsureValid(markingManager);
|
||||||
|
|
||||||
@@ -223,8 +251,10 @@ namespace Content.Shared.Humanoid
|
|||||||
}
|
}
|
||||||
|
|
||||||
markingSet.EnsureSpecies(species, skinColor, markingManager);
|
markingSet.EnsureSpecies(species, skinColor, markingManager);
|
||||||
markingSet.EnsureSexes(sex, markingManager);
|
|
||||||
}
|
// WD-EDIT
|
||||||
|
markingSet.FilterSponsor(sponsorMarkings, markingManager);
|
||||||
|
// WD-EDIT
|
||||||
|
|
||||||
return new HumanoidCharacterAppearance(
|
return new HumanoidCharacterAppearance(
|
||||||
hairStyleId,
|
hairStyleId,
|
||||||
@@ -238,15 +268,21 @@ namespace Content.Shared.Humanoid
|
|||||||
|
|
||||||
public bool MemberwiseEquals(ICharacterAppearance maybeOther)
|
public bool MemberwiseEquals(ICharacterAppearance maybeOther)
|
||||||
{
|
{
|
||||||
if (maybeOther is not HumanoidCharacterAppearance other) return false;
|
if (maybeOther is not HumanoidCharacterAppearance other)
|
||||||
if (HairStyleId != other.HairStyleId) return false;
|
return false;
|
||||||
if (!HairColor.Equals(other.HairColor)) return false;
|
if (HairStyleId != other.HairStyleId)
|
||||||
if (FacialHairStyleId != other.FacialHairStyleId) return false;
|
return false;
|
||||||
if (!FacialHairColor.Equals(other.FacialHairColor)) return false;
|
if (!HairColor.Equals(other.HairColor))
|
||||||
if (!EyeColor.Equals(other.EyeColor)) return false;
|
return false;
|
||||||
if (!SkinColor.Equals(other.SkinColor)) return false;
|
if (FacialHairStyleId != other.FacialHairStyleId)
|
||||||
if (!Markings.SequenceEqual(other.Markings)) return false;
|
return false;
|
||||||
return true;
|
if (!FacialHairColor.Equals(other.FacialHairColor))
|
||||||
|
return false;
|
||||||
|
if (!EyeColor.Equals(other.EyeColor))
|
||||||
|
return false;
|
||||||
|
if (!SkinColor.Equals(other.SkinColor))
|
||||||
|
return false;
|
||||||
|
return Markings.SequenceEqual(other.Markings);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,10 @@ namespace Content.Shared.Humanoid.Markings
|
|||||||
[DataField("sexRestriction")]
|
[DataField("sexRestriction")]
|
||||||
public Sex? SexRestriction { get; private set; }
|
public Sex? SexRestriction { get; private set; }
|
||||||
|
|
||||||
|
// WD-EDIT
|
||||||
|
[DataField("sponsorOnly")] public bool SponsorOnly;
|
||||||
|
// WD-EDIT
|
||||||
|
|
||||||
[DataField("followSkinColor")]
|
[DataField("followSkinColor")]
|
||||||
public bool FollowSkinColor { get; private set; } = false;
|
public bool FollowSkinColor { get; private set; } = false;
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ using System.Linq;
|
|||||||
using Content.Shared.Humanoid.Prototypes;
|
using Content.Shared.Humanoid.Prototypes;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
using Robust.Shared.Utility;
|
|
||||||
|
|
||||||
namespace Content.Shared.Humanoid.Markings;
|
namespace Content.Shared.Humanoid.Markings;
|
||||||
|
|
||||||
@@ -265,6 +264,37 @@ public sealed partial class MarkingSet
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WD-EDIT
|
||||||
|
public void FilterSponsor(string[] sponsorMarkings, MarkingManager? markingManager = null, IPrototypeManager? prototypeManager = null)
|
||||||
|
{
|
||||||
|
IoCManager.Resolve(ref markingManager);
|
||||||
|
IoCManager.Resolve(ref prototypeManager);
|
||||||
|
|
||||||
|
var toRemove = new List<(MarkingCategories category, string id)>();
|
||||||
|
foreach (var (category, list) in Markings)
|
||||||
|
{
|
||||||
|
foreach (var marking in list)
|
||||||
|
{
|
||||||
|
if (prototypeManager.TryIndex<MarkingPrototype>(marking.MarkingId, out var proto) && !proto.SponsorOnly)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var allowedToHave = sponsorMarkings.Contains(marking.MarkingId);
|
||||||
|
if (!allowedToHave)
|
||||||
|
{
|
||||||
|
toRemove.Add((category, marking.MarkingId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var marking in toRemove)
|
||||||
|
{
|
||||||
|
Remove(marking.category, marking.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// WD-EDIT
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Ensures that the default markings as defined by the marking point set in this marking set are applied.
|
/// Ensures that the default markings as defined by the marking point set in this marking set are applied.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -350,7 +350,7 @@ namespace Content.Shared.Preferences
|
|||||||
return Appearance.MemberwiseEquals(other.Appearance);
|
return Appearance.MemberwiseEquals(other.Appearance);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void EnsureValid()
|
public void EnsureValid(string[] sponsorMarkings) //WD-EDIT
|
||||||
{
|
{
|
||||||
var prototypeManager = IoCManager.Resolve<IPrototypeManager>();
|
var prototypeManager = IoCManager.Resolve<IPrototypeManager>();
|
||||||
|
|
||||||
@@ -433,7 +433,9 @@ namespace Content.Shared.Preferences
|
|||||||
flavortext = FormattedMessage.RemoveMarkup(FlavorText);
|
flavortext = FormattedMessage.RemoveMarkup(FlavorText);
|
||||||
}
|
}
|
||||||
|
|
||||||
var appearance = HumanoidCharacterAppearance.EnsureValid(Appearance, Species, Sex);
|
// WD-EDIT
|
||||||
|
var appearance = HumanoidCharacterAppearance.EnsureValid(Appearance, Species, sponsorMarkings);
|
||||||
|
// WD-EDIT
|
||||||
|
|
||||||
var prefsUnavailableMode = PreferenceUnavailable switch
|
var prefsUnavailableMode = PreferenceUnavailable switch
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -13,6 +13,6 @@ namespace Content.Shared.Preferences
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Makes this profile valid so there's no bad data like negative ages.
|
/// Makes this profile valid so there's no bad data like negative ages.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void EnsureValid();
|
void EnsureValid(string[] sponsorMarkings); //WD-EDIT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
36
Content.Shared/White/JoinQueue/MsgQueueUpdate.cs
Normal file
36
Content.Shared/White/JoinQueue/MsgQueueUpdate.cs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
using Lidgren.Network;
|
||||||
|
using Robust.Shared.Network;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
|
namespace Content.Shared.White.JoinQueue;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sent from server to client with queue state for player
|
||||||
|
/// Also initiates queue state on client
|
||||||
|
/// </summary>
|
||||||
|
public sealed class MsgQueueUpdate : 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; }
|
||||||
|
|
||||||
|
public override void ReadFromBuffer(NetIncomingMessage buffer, IRobustSerializer serializer)
|
||||||
|
{
|
||||||
|
Total = buffer.ReadInt32();
|
||||||
|
Position = buffer.ReadInt32();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void WriteToBuffer(NetOutgoingMessage buffer, IRobustSerializer serializer)
|
||||||
|
{
|
||||||
|
buffer.Write(Total);
|
||||||
|
buffer.Write(Position);
|
||||||
|
}
|
||||||
|
}
|
||||||
62
Content.Shared/White/Sponsors/MsgSponsorInfo.cs
Normal file
62
Content.Shared/White/Sponsors/MsgSponsorInfo.cs
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
using System.IO;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using Lidgren.Network;
|
||||||
|
using Robust.Shared.Network;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
|
namespace Content.Shared.White.Sponsors;
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed class SponsorInfo
|
||||||
|
{
|
||||||
|
[JsonPropertyName("tier")]
|
||||||
|
public int? Tier { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("oocColor")]
|
||||||
|
public string? OOCColor { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("priorityJoin")]
|
||||||
|
public bool HavePriorityJoin { get; set; } = false;
|
||||||
|
|
||||||
|
[JsonPropertyName("allowedMarkings")]
|
||||||
|
public string[] AllowedMarkings { get; set; } = Array.Empty<string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Server sends sponsoring info to client on connect only if user is sponsor
|
||||||
|
/// </summary>
|
||||||
|
public sealed class MsgSponsorInfo : NetMessage
|
||||||
|
{
|
||||||
|
public override MsgGroups MsgGroup => MsgGroups.Command;
|
||||||
|
|
||||||
|
public SponsorInfo? Info;
|
||||||
|
|
||||||
|
public override void ReadFromBuffer(NetIncomingMessage buffer, IRobustSerializer serializer)
|
||||||
|
{
|
||||||
|
var isSponsor = buffer.ReadBoolean();
|
||||||
|
buffer.ReadPadBits();
|
||||||
|
|
||||||
|
if (!isSponsor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var length = buffer.ReadVariableInt32();
|
||||||
|
using var stream = new MemoryStream(length);
|
||||||
|
buffer.ReadAlignedMemory(stream, length);
|
||||||
|
serializer.DeserializeDirect(stream, out Info);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void WriteToBuffer(NetOutgoingMessage buffer, IRobustSerializer serializer)
|
||||||
|
{
|
||||||
|
buffer.Write(Info != null);
|
||||||
|
buffer.WritePadBits();
|
||||||
|
|
||||||
|
if (Info == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var stream = new MemoryStream();
|
||||||
|
serializer.SerializeDirect(stream, Info);
|
||||||
|
buffer.WriteVariableInt32((int) stream.Length);
|
||||||
|
buffer.Write(stream.AsSpan());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,4 +18,20 @@ public sealed class WhiteCVars
|
|||||||
|
|
||||||
public static readonly CVarDef<bool> ChatSlangFilter =
|
public static readonly CVarDef<bool> ChatSlangFilter =
|
||||||
CVarDef.Create("ic.slang_filter", true, CVar.SERVER | CVar.REPLICATED | CVar.ARCHIVE);
|
CVarDef.Create("ic.slang_filter", true, CVar.SERVER | CVar.REPLICATED | CVar.ARCHIVE);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sponsors
|
||||||
|
*/
|
||||||
|
|
||||||
|
public static readonly CVarDef<string> SponsorsApiUrl =
|
||||||
|
CVarDef.Create("sponsor.api_url", "", CVar.SERVERONLY);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Queue
|
||||||
|
*/
|
||||||
|
|
||||||
|
public static readonly CVarDef<bool>
|
||||||
|
QueueEnabled = CVarDef.Create("queue.enabled", false, CVar.SERVERONLY);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
bodyPart: HeadTop
|
bodyPart: HeadTop
|
||||||
markingCategory: HeadTop
|
markingCategory: HeadTop
|
||||||
speciesRestriction: [Human]
|
speciesRestriction: [Human]
|
||||||
|
sponsorOnly: true
|
||||||
coloring:
|
coloring:
|
||||||
default:
|
default:
|
||||||
type:
|
type:
|
||||||
@@ -26,6 +27,7 @@
|
|||||||
bodyPart: Tail
|
bodyPart: Tail
|
||||||
markingCategory: Tail
|
markingCategory: Tail
|
||||||
speciesRestriction: [Human]
|
speciesRestriction: [Human]
|
||||||
|
sponsorOnly: true
|
||||||
coloring:
|
coloring:
|
||||||
default:
|
default:
|
||||||
type:
|
type:
|
||||||
|
|||||||
@@ -21,6 +21,8 @@
|
|||||||
Hair: MobHumanoidAnyMarking
|
Hair: MobHumanoidAnyMarking
|
||||||
FacialHair: MobHumanoidAnyMarking
|
FacialHair: MobHumanoidAnyMarking
|
||||||
Chest: MobHumanTorso
|
Chest: MobHumanTorso
|
||||||
|
HeadTop: MobHumanoidAnyMarking
|
||||||
|
Tail: MobHumanoidAnyMarking
|
||||||
Eyes: MobHumanoidEyes
|
Eyes: MobHumanoidEyes
|
||||||
LArm: MobHumanLArm
|
LArm: MobHumanLArm
|
||||||
RArm: MobHumanRArm
|
RArm: MobHumanRArm
|
||||||
@@ -41,10 +43,10 @@
|
|||||||
points: 1
|
points: 1
|
||||||
required: false
|
required: false
|
||||||
Tail: # the cat tail joke
|
Tail: # the cat tail joke
|
||||||
points: 0
|
points: 1
|
||||||
required: false
|
required: false
|
||||||
HeadTop: # the cat ear joke
|
HeadTop: # the cat ear joke
|
||||||
points: 0
|
points: 1
|
||||||
required: false
|
required: false
|
||||||
Chest:
|
Chest:
|
||||||
points: 1
|
points: 1
|
||||||
|
|||||||
Reference in New Issue
Block a user