using Robust.Shared.Configuration;
using Robust.Shared.IoC;
using Robust.Shared.Timing;
-using Robust.Shared.Localization;
using Robust.Shared.Network;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
{
private const float RedialWaitTimeSeconds = 15f;
private readonly LauncherConnecting _state;
+ private float _waitTime;
+
+ // Pressing reconnect will redial instead of simply reconnecting.
+ private bool _redial;
+
private readonly IRobustRandom _random;
private readonly IPrototypeManager _prototype;
private readonly IConfigurationManager _cfg;
- private float _redialWaitTime = RedialWaitTimeSeconds;
-
public LauncherConnectingGui(LauncherConnecting state, IRobustRandom random,
IPrototypeManager prototype, IConfigurationManager config)
{
Stylesheet = IoCManager.Resolve<IStylesheetManager>().SheetSpace;
ChangeLoginTip();
- ReconnectButton.OnPressed += _ => _state.RetryConnect();
- // Redial shouldn't fail, but if it does, try a reconnect (maybe we're being run from debug)
- RedialButton.OnPressed += _ =>
- {
- if (!_state.Redial())
- _state.RetryConnect();
- };
- RetryButton.OnPressed += _ => _state.RetryConnect();
+ ReconnectButton.OnPressed += ReconnectButtonPressed;
+ RetryButton.OnPressed += ReconnectButtonPressed;
ExitButton.OnPressed += _ => _state.Exit();
var addr = state.Address;
state.PageChanged += OnPageChanged;
state.ConnectFailReasonChanged += ConnectFailReasonChanged;
state.ConnectionStateChanged += ConnectionStateChanged;
+ state.ConnectFailed += HandleDisconnectReason;
ConnectionStateChanged(state.ConnectionState);
LastNetDisconnectedArgsChanged(edim.LastNetDisconnectedArgs);
}
+ // Just button, there's only one at once anyways :)
+ private void ReconnectButtonPressed(BaseButton.ButtonEventArgs args)
+ {
+ if (_redial)
+ {
+ // Redial shouldn't fail, but if it does, try a reconnect (maybe we're being run from debug)
+ if (_state.Redial())
+ return;
+ }
+
+ _state.RetryConnect();
+ }
+
private void ConnectFailReasonChanged(string? reason)
{
ConnectFailReason.SetMessage(reason == null
private void LastNetDisconnectedArgsChanged(NetDisconnectedArgs? args)
{
- var redialFlag = args?.RedialFlag ?? false;
- RedialButton.Visible = redialFlag;
- ReconnectButton.Visible = !redialFlag;
+ HandleDisconnectReason(args);
+ }
+
+ private void HandleDisconnectReason(INetStructuredReason? reason)
+ {
+ if (reason == null)
+ {
+ _waitTime = 0;
+ _redial = false;
+ }
+ else
+ {
+ _redial = reason.RedialFlag;
+
+ if (reason.Message.Int32Of("delay") is { } delay)
+ {
+ _waitTime = delay;
+ }
+ else if (_redial)
+ {
+ _waitTime = RedialWaitTimeSeconds;
+ }
+
+ }
}
private void ChangeLoginTip()
protected override void FrameUpdate(FrameEventArgs args)
{
base.FrameUpdate(args);
- _redialWaitTime -= args.DeltaSeconds;
- if (_redialWaitTime <= 0)
+
+ var button = _state.CurrentPage == LauncherConnecting.Page.ConnectFailed
+ ? RetryButton
+ : ReconnectButton;
+
+ _waitTime -= args.DeltaSeconds;
+ if (_waitTime <= 0)
{
- RedialButton.Disabled = false;
- RedialButton.Text = Loc.GetString("connecting-redial");
+ button.Disabled = false;
+ var key = _redial
+ ? "connecting-redial"
+ : _state.CurrentPage == LauncherConnecting.Page.ConnectFailed
+ ? "connecting-reconnect"
+ : "connecting-retry";
+
+ button.Text = Loc.GetString(key);
}
else
{
- RedialButton.Disabled = true;
- RedialButton.Text = Loc.GetString("connecting-redial-wait", ("time", _redialWaitTime.ToString("00.000")));
+ button.Disabled = true;
+ button.Text = Loc.GetString("connecting-redial-wait", ("time", _waitTime.ToString("00.000")));
}
}
using System.Collections.Immutable;
+using System.Text.Json.Nodes;
using System.Threading.Tasks;
using Content.Server.Database;
using Content.Server.GameTicking;
if (banHits is { Count: > 0 })
await _db.AddServerBanHitsAsync(id, banHits);
- e.Deny(msg);
+ var properties = new Dictionary<string, object>();
+ if (reason == ConnectionDenyReason.Full)
+ properties["delay"] = _cfg.GetCVar(CCVars.GameServerFullReconnectDelay);
+
+ e.Deny(new NetDenyReason(msg, properties));
}
else
{
var wasInGame = EntitySystem.TryGet<GameTicker>(out var ticker) &&
ticker.PlayerGameStatuses.TryGetValue(userId, out var status) &&
status == PlayerGameStatus.JoinedGame;
- if ((_plyMgr.PlayerCount >= _cfg.GetCVar(CCVars.SoftMaxPlayers) && adminData is null) && !wasInGame)
+ var adminBypass = _cfg.GetCVar(CCVars.AdminBypassMaxPlayers) && adminData != null;
+ if ((_plyMgr.PlayerCount >= _cfg.GetCVar(CCVars.SoftMaxPlayers) && !adminBypass) && !wasInGame)
{
return (ConnectionDenyReason.Full, Loc.GetString("soft-player-cap-full"), null);
}
public static readonly CVarDef<int> SoftMaxPlayers =
CVarDef.Create("game.soft_max_players", 30, CVar.SERVERONLY | CVar.ARCHIVE);
+ /// <summary>
+ /// If a player gets denied connection to the server,
+ /// how long they are forced to wait before attempting to reconnect.
+ /// </summary>
+ public static readonly CVarDef<int> GameServerFullReconnectDelay =
+ CVarDef.Create("game.server_full_reconnect_delay", 30, CVar.SERVERONLY);
+
/// <summary>
/// Whether or not panic bunker is currently enabled.
/// </summary>
public static readonly CVarDef<float> AdminAfkTime =
CVarDef.Create("admin.afk_time", 600f, CVar.SERVERONLY);
+ /// <summary>
+ /// If true, admins are able to connect even if
+ /// <see cref="SoftMaxPlayers"/> would otherwise block regular players.
+ /// </summary>
+ public static readonly CVarDef<bool> AdminBypassMaxPlayers =
+ CVarDef.Create("admin.bypass_max_players", true, CVar.SERVERONLY);
+
/*
* Explosions
*/