* grass touch protocol - Rebases to latest master to fix conflicts * aight local tests are passing lets see if our golf works * It is 5 am and our ass COMPLETELY overcomplicated this lmaooo * Addresses feedback - Clarifies comments, swaps internal var names for grasstouchless and selfdestructive, makes the third tier a little less demanding, and fixes 1 hours * Addresses review - conflict fix * This too * Axes playtime exclusion for ghosts * Use switch expression code style nit * Refactor/cleanup Use IGameTiming.RealTime to track time instead of DateTime. Use nullable instead of magic values. Expose the current day value through a property that is always up to date, instead of making the API to read the CVar that updates at inconsistent times. This also makes it trivial to debug with VV. Other minor cleanup like using string interp, code style fixes, comments, etc. --------- Co-authored-by: PJB3005 <pieterjan.briers+git@gmail.com>
275 lines
10 KiB
C#
275 lines
10 KiB
C#
using Content.Client.Audio;
|
|
using Content.Client.GameTicking.Managers;
|
|
using Content.Client.LateJoin;
|
|
using Content.Client.Lobby.UI;
|
|
using Content.Client.Message;
|
|
using Content.Client.Playtime;
|
|
using Content.Client.UserInterface.Systems.Chat;
|
|
using Content.Client.Voting;
|
|
using Content.Shared.CCVar;
|
|
using Robust.Client;
|
|
using Robust.Client.Console;
|
|
using Robust.Client.ResourceManagement;
|
|
using Robust.Client.UserInterface;
|
|
using Robust.Client.UserInterface.Controls;
|
|
using Robust.Shared.Configuration;
|
|
using Robust.Shared.Timing;
|
|
|
|
namespace Content.Client.Lobby
|
|
{
|
|
public sealed class LobbyState : Robust.Client.State.State
|
|
{
|
|
[Dependency] private readonly IBaseClient _baseClient = default!;
|
|
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
|
[Dependency] private readonly IClientConsoleHost _consoleHost = default!;
|
|
[Dependency] private readonly IEntityManager _entityManager = default!;
|
|
[Dependency] private readonly IResourceCache _resourceCache = default!;
|
|
[Dependency] private readonly IUserInterfaceManager _userInterfaceManager = default!;
|
|
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
|
[Dependency] private readonly IVoteManager _voteManager = default!;
|
|
[Dependency] private readonly ClientsidePlaytimeTrackingManager _playtimeTracking = default!;
|
|
|
|
private ClientGameTicker _gameTicker = default!;
|
|
private ContentAudioSystem _contentAudioSystem = default!;
|
|
|
|
protected override Type? LinkedScreenType { get; } = typeof(LobbyGui);
|
|
public LobbyGui? Lobby;
|
|
|
|
protected override void Startup()
|
|
{
|
|
if (_userInterfaceManager.ActiveScreen == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Lobby = (LobbyGui) _userInterfaceManager.ActiveScreen;
|
|
|
|
var chatController = _userInterfaceManager.GetUIController<ChatUIController>();
|
|
_gameTicker = _entityManager.System<ClientGameTicker>();
|
|
_contentAudioSystem = _entityManager.System<ContentAudioSystem>();
|
|
_contentAudioSystem.LobbySoundtrackChanged += UpdateLobbySoundtrackInfo;
|
|
|
|
chatController.SetMainChat(true);
|
|
|
|
_voteManager.SetPopupContainer(Lobby.VoteContainer);
|
|
LayoutContainer.SetAnchorPreset(Lobby, LayoutContainer.LayoutPreset.Wide);
|
|
|
|
var lobbyNameCvar = _cfg.GetCVar(CCVars.ServerLobbyName);
|
|
var serverName = _baseClient.GameInfo?.ServerName ?? string.Empty;
|
|
|
|
Lobby.ServerName.Text = string.IsNullOrEmpty(lobbyNameCvar)
|
|
? Loc.GetString("ui-lobby-title", ("serverName", serverName))
|
|
: lobbyNameCvar;
|
|
|
|
var width = _cfg.GetCVar(CCVars.ServerLobbyRightPanelWidth);
|
|
Lobby.RightSide.SetWidth = width;
|
|
|
|
UpdateLobbyUi();
|
|
|
|
Lobby.CharacterPreview.CharacterSetupButton.OnPressed += OnSetupPressed;
|
|
Lobby.ReadyButton.OnPressed += OnReadyPressed;
|
|
Lobby.ReadyButton.OnToggled += OnReadyToggled;
|
|
|
|
_gameTicker.InfoBlobUpdated += UpdateLobbyUi;
|
|
_gameTicker.LobbyStatusUpdated += LobbyStatusUpdated;
|
|
_gameTicker.LobbyLateJoinStatusUpdated += LobbyLateJoinStatusUpdated;
|
|
}
|
|
|
|
protected override void Shutdown()
|
|
{
|
|
var chatController = _userInterfaceManager.GetUIController<ChatUIController>();
|
|
chatController.SetMainChat(false);
|
|
_gameTicker.InfoBlobUpdated -= UpdateLobbyUi;
|
|
_gameTicker.LobbyStatusUpdated -= LobbyStatusUpdated;
|
|
_gameTicker.LobbyLateJoinStatusUpdated -= LobbyLateJoinStatusUpdated;
|
|
_contentAudioSystem.LobbySoundtrackChanged -= UpdateLobbySoundtrackInfo;
|
|
|
|
_voteManager.ClearPopupContainer();
|
|
|
|
Lobby!.CharacterPreview.CharacterSetupButton.OnPressed -= OnSetupPressed;
|
|
Lobby!.ReadyButton.OnPressed -= OnReadyPressed;
|
|
Lobby!.ReadyButton.OnToggled -= OnReadyToggled;
|
|
|
|
Lobby = null;
|
|
}
|
|
|
|
public void SwitchState(LobbyGui.LobbyGuiState state)
|
|
{
|
|
// Yeah I hate this but LobbyState contains all the badness for now.
|
|
Lobby?.SwitchState(state);
|
|
}
|
|
|
|
private void OnSetupPressed(BaseButton.ButtonEventArgs args)
|
|
{
|
|
SetReady(false);
|
|
Lobby?.SwitchState(LobbyGui.LobbyGuiState.CharacterSetup);
|
|
}
|
|
|
|
private void OnReadyPressed(BaseButton.ButtonEventArgs args)
|
|
{
|
|
if (!_gameTicker.IsGameStarted)
|
|
{
|
|
return;
|
|
}
|
|
|
|
new LateJoinGui().OpenCentered();
|
|
}
|
|
|
|
private void OnReadyToggled(BaseButton.ButtonToggledEventArgs args)
|
|
{
|
|
SetReady(args.Pressed);
|
|
}
|
|
|
|
public override void FrameUpdate(FrameEventArgs e)
|
|
{
|
|
if (_gameTicker.IsGameStarted)
|
|
{
|
|
Lobby!.StartTime.Text = string.Empty;
|
|
var roundTime = _gameTiming.CurTime.Subtract(_gameTicker.RoundStartTimeSpan);
|
|
Lobby!.StationTime.Text = Loc.GetString("lobby-state-player-status-round-time", ("hours", roundTime.Hours), ("minutes", roundTime.Minutes));
|
|
return;
|
|
}
|
|
|
|
Lobby!.StationTime.Text = Loc.GetString("lobby-state-player-status-round-not-started");
|
|
string text;
|
|
|
|
if (_gameTicker.Paused)
|
|
{
|
|
text = Loc.GetString("lobby-state-paused");
|
|
}
|
|
else if (_gameTicker.StartTime < _gameTiming.CurTime)
|
|
{
|
|
Lobby!.StartTime.Text = Loc.GetString("lobby-state-soon");
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
var difference = _gameTicker.StartTime - _gameTiming.CurTime;
|
|
var seconds = difference.TotalSeconds;
|
|
if (seconds < 0)
|
|
{
|
|
text = Loc.GetString(seconds < -5 ? "lobby-state-right-now-question" : "lobby-state-right-now-confirmation");
|
|
}
|
|
else if (difference.TotalHours >= 1)
|
|
{
|
|
text = $"{Math.Floor(difference.TotalHours)}:{difference.Minutes:D2}:{difference.Seconds:D2}";
|
|
}
|
|
else
|
|
{
|
|
text = $"{difference.Minutes}:{difference.Seconds:D2}";
|
|
}
|
|
}
|
|
|
|
Lobby!.StartTime.Text = Loc.GetString("lobby-state-round-start-countdown-text", ("timeLeft", text));
|
|
}
|
|
|
|
private void LobbyStatusUpdated()
|
|
{
|
|
UpdateLobbyBackground();
|
|
UpdateLobbyUi();
|
|
}
|
|
|
|
private void LobbyLateJoinStatusUpdated()
|
|
{
|
|
Lobby!.ReadyButton.Disabled = _gameTicker.DisallowedLateJoin;
|
|
}
|
|
|
|
private void UpdateLobbyUi()
|
|
{
|
|
if (_gameTicker.IsGameStarted)
|
|
{
|
|
Lobby!.ReadyButton.Text = Loc.GetString("lobby-state-ready-button-join-state");
|
|
Lobby!.ReadyButton.ToggleMode = false;
|
|
Lobby!.ReadyButton.Pressed = false;
|
|
Lobby!.ObserveButton.Disabled = false;
|
|
}
|
|
else
|
|
{
|
|
Lobby!.StartTime.Text = string.Empty;
|
|
Lobby!.ReadyButton.Text = Loc.GetString(Lobby!.ReadyButton.Pressed ? "lobby-state-player-status-ready": "lobby-state-player-status-not-ready");
|
|
Lobby!.ReadyButton.ToggleMode = true;
|
|
Lobby!.ReadyButton.Disabled = false;
|
|
Lobby!.ReadyButton.Pressed = _gameTicker.AreWeReady;
|
|
Lobby!.ObserveButton.Disabled = true;
|
|
}
|
|
|
|
if (_gameTicker.ServerInfoBlob != null)
|
|
{
|
|
Lobby!.ServerInfo.SetInfoBlob(_gameTicker.ServerInfoBlob);
|
|
}
|
|
|
|
var minutesToday = _playtimeTracking.PlaytimeMinutesToday;
|
|
if (minutesToday > 60)
|
|
{
|
|
Lobby!.PlaytimeComment.Visible = true;
|
|
|
|
var hoursToday = Math.Round(minutesToday / 60f, 1);
|
|
|
|
var chosenString = minutesToday switch
|
|
{
|
|
< 180 => "lobby-state-playtime-comment-normal",
|
|
< 360 => "lobby-state-playtime-comment-concerning",
|
|
< 720 => "lobby-state-playtime-comment-grasstouchless",
|
|
_ => "lobby-state-playtime-comment-selfdestructive"
|
|
};
|
|
|
|
Lobby.PlaytimeComment.SetMarkup(Loc.GetString(chosenString, ("hours", hoursToday)));
|
|
}
|
|
else
|
|
Lobby!.PlaytimeComment.Visible = false;
|
|
}
|
|
|
|
private void UpdateLobbySoundtrackInfo(LobbySoundtrackChangedEvent ev)
|
|
{
|
|
if (ev.SoundtrackFilename == null)
|
|
{
|
|
Lobby!.LobbySong.SetMarkup(Loc.GetString("lobby-state-song-no-song-text"));
|
|
}
|
|
else if (
|
|
ev.SoundtrackFilename != null
|
|
&& _resourceCache.TryGetResource<AudioResource>(ev.SoundtrackFilename, out var lobbySongResource)
|
|
)
|
|
{
|
|
var lobbyStream = lobbySongResource.AudioStream;
|
|
|
|
var title = string.IsNullOrEmpty(lobbyStream.Title)
|
|
? Loc.GetString("lobby-state-song-unknown-title")
|
|
: lobbyStream.Title;
|
|
|
|
var artist = string.IsNullOrEmpty(lobbyStream.Artist)
|
|
? Loc.GetString("lobby-state-song-unknown-artist")
|
|
: lobbyStream.Artist;
|
|
|
|
var markup = Loc.GetString("lobby-state-song-text",
|
|
("songTitle", title),
|
|
("songArtist", artist));
|
|
|
|
Lobby!.LobbySong.SetMarkup(markup);
|
|
}
|
|
}
|
|
|
|
private void UpdateLobbyBackground()
|
|
{
|
|
if (_gameTicker.LobbyBackground != null)
|
|
{
|
|
Lobby!.Background.Texture = _resourceCache.GetResource<TextureResource>(_gameTicker.LobbyBackground );
|
|
}
|
|
else
|
|
{
|
|
Lobby!.Background.Texture = null;
|
|
}
|
|
|
|
}
|
|
|
|
private void SetReady(bool newReady)
|
|
{
|
|
if (_gameTicker.IsGameStarted)
|
|
{
|
|
return;
|
|
}
|
|
|
|
_consoleHost.ExecuteCommand($"toggleready {newReady}");
|
|
}
|
|
}
|
|
}
|