From 0f8b83a9d39fc32af0dc693f10645bb26c261fbc Mon Sep 17 00:00:00 2001 From: Whatstone Date: Thu, 17 Oct 2024 18:36:32 -0400 Subject: [PATCH 1/6] Fix round end text --- Content.Server/_NF/GameRule/NfAdventureRuleSystem.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Content.Server/_NF/GameRule/NfAdventureRuleSystem.cs b/Content.Server/_NF/GameRule/NfAdventureRuleSystem.cs index c6b88987d95..237312cca5e 100644 --- a/Content.Server/_NF/GameRule/NfAdventureRuleSystem.cs +++ b/Content.Server/_NF/GameRule/NfAdventureRuleSystem.cs @@ -33,6 +33,7 @@ using Content.Shared.Tiles; using Content.Server._NF.PublicTransit.Components; using Content.Server._NF.GameRule.Components; +using Content.Server.Bank; namespace Content.Server._NF.GameRule; @@ -51,6 +52,7 @@ public sealed class NfAdventureRuleSystem : GameRuleSystem(player.Item1, out var bank) || !TryComp(player.Item1, out var meta)) + if (!_bank.TryGetBalance(player.Item1, out var bankBalance) || !TryComp(player.Item1, out var meta)) continue; - var profit = bank.Balance - player.Item2; + var profit = bankBalance - player.Item2; ev.AddLine($"- {meta.EntityName} {profitText} {profit} Spesos"); allScore.Add(new Tuple(meta.EntityName, profit)); } From 0c163d65b4f8f14c0969406cb74ec712a07d7abe Mon Sep 17 00:00:00 2001 From: Whatstone Date: Fri, 18 Oct 2024 01:28:02 -0400 Subject: [PATCH 2/6] 90% done, missing disconnect handling --- Content.Server/_NF/Bank/BankEvents.cs | 19 ++++ Content.Server/_NF/Bank/BankSystem.cs | 32 +++++- .../_NF/GameRule/NfAdventureRuleSystem.cs | 103 +++++++++++++++--- .../Locale/en-US/_NF/adventure/adventure.ftl | 12 +- .../round-end/round-end-summary-window.ftl | 5 +- 5 files changed, 145 insertions(+), 26 deletions(-) create mode 100644 Content.Server/_NF/Bank/BankEvents.cs diff --git a/Content.Server/_NF/Bank/BankEvents.cs b/Content.Server/_NF/Bank/BankEvents.cs new file mode 100644 index 00000000000..cfbc0d4e5cf --- /dev/null +++ b/Content.Server/_NF/Bank/BankEvents.cs @@ -0,0 +1,19 @@ +namespace Content.Server.Bank; + +public sealed class BankAccountAddedEvent : EntityEventArgs +{ + public EntityUid Entity; + public BankAccountAddedEvent(EntityUid entity) + { + Entity = entity; + } +} + +public sealed class BankAccountRemovedEvent : EntityEventArgs +{ + public EntityUid Entity; + public BankAccountRemovedEvent(EntityUid entity) + { + Entity = entity; + } +} diff --git a/Content.Server/_NF/Bank/BankSystem.cs b/Content.Server/_NF/Bank/BankSystem.cs index 18c7670e181..392f73e3471 100644 --- a/Content.Server/_NF/Bank/BankSystem.cs +++ b/Content.Server/_NF/Bank/BankSystem.cs @@ -208,11 +208,11 @@ public bool TryBankDeposit(ICommonSession session, PlayerPreferences prefs, Huma } /// - /// Attempts to add money to a character's bank account. This should always be used instead of attempting to modify the bankaccountcomponent directly + /// Retrieves a character's balance via its in-game entity, if it has one. /// /// The UID that the bank account is connected to, typically the player controlled mob - /// The amount of spesos to add into the bank account - /// true if the transaction was successful, false if it was not + /// When successful, contains the account balance in spesos. Otherwise, set to 0. + /// true if the account was successfully queried. public bool TryGetBalance(EntityUid ent, out int balance) { if (!_playerManager.TryGetSessionByEntity(ent, out var session) || @@ -234,6 +234,32 @@ public bool TryGetBalance(EntityUid ent, out int balance) return true; } + /// + /// Retrieves a character's balance via a player's session. + /// + /// The session of the player character to query. + /// When successful, contains the account balance in spesos. Otherwise, set to 0. + /// true if the account was successfully queried. + public bool TryGetBalance(ICommonSession session, out int balance) + { + if (!_prefsManager.TryGetCachedPreferences(session.UserId, out var prefs)) + { + _log.Info($"{session} has no cached prefs"); + balance = 0; + return false; + } + + if (prefs.SelectedCharacter is not HumanoidCharacterProfile profile) + { + _log.Info($"{session} has the wrong prefs type"); + balance = 0; + return false; + } + + balance = profile.BankBalance; + return true; + } + /// /// Update the bank balance to the character's current account balance. /// diff --git a/Content.Server/_NF/GameRule/NfAdventureRuleSystem.cs b/Content.Server/_NF/GameRule/NfAdventureRuleSystem.cs index 237312cca5e..6e710fb43a7 100644 --- a/Content.Server/_NF/GameRule/NfAdventureRuleSystem.cs +++ b/Content.Server/_NF/GameRule/NfAdventureRuleSystem.cs @@ -7,7 +7,6 @@ using System.Threading.Tasks; using Content.Shared._NF.GameRule; using Content.Server.Procedural; -using Content.Shared.Bank.Components; using Content.Server._NF.GameTicking.Events; using Content.Shared.Procedural; using Robust.Server.GameObjects; @@ -30,10 +29,14 @@ using Robust.Shared.Configuration; using Robust.Shared.Physics.Components; using Content.Server.Shuttles.Components; +using Content.Shared._NF.Bank; using Content.Shared.Tiles; using Content.Server._NF.PublicTransit.Components; using Content.Server._NF.GameRule.Components; using Content.Server.Bank; +using Robust.Shared.Player; +using Robust.Shared.Network; +using Content.Shared.GameTicking; namespace Content.Server._NF.GameRule; @@ -56,8 +59,30 @@ public sealed class NfAdventureRuleSystem : GameRuleSystem _players = new(); + private Dictionary _players = new(); private float _distanceOffset = 1f; private List _stationCoords = new(); @@ -69,23 +94,39 @@ public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnPlayerSpawningEvent); + SubscribeLocalEvent(OnPlayerDetachedEvent); + SubscribeLocalEvent(OnRoundRestart); } protected override void AppendRoundEndText(EntityUid uid, AdventureRuleComponent component, GameRuleComponent gameRule, ref RoundEndTextAppendEvent ev) { - var profitText = Loc.GetString($"adventure-mode-profit-text"); - var lossText = Loc.GetString($"adventure-mode-loss-text"); ev.AddLine(Loc.GetString("adventure-list-start")); var allScore = new List>(); - foreach (var player in _players) + foreach (var (player, playerInfo) in _players) { - if (!_bank.TryGetBalance(player.Item1, out var bankBalance) || !TryComp(player.Item1, out var meta)) + var endBalance = playerInfo.EndBalance; + if (_bank.TryGetBalance(player, out var bankBalance)) + { + endBalance = bankBalance; + } + + // Check if endBalance is valid (non-negative) + if (endBalance < 0) continue; - var profit = bankBalance - player.Item2; - ev.AddLine($"- {meta.EntityName} {profitText} {profit} Spesos"); - allScore.Add(new Tuple(meta.EntityName, profit)); + var profit = endBalance - playerInfo.StartBalance; + string summaryText; + if (profit < 0) + { + summaryText = Loc.GetString("adventure-mode-list-loss", ("amount", BankSystemExtensions.ToSpesoString(-profit))); + } + else + { + summaryText = Loc.GetString("adventure-mode-list-profit", ("amount", BankSystemExtensions.ToSpesoString(profit))); + } + ev.AddLine($"- {playerInfo.Name} {summaryText}"); + allScore.Add(new Tuple(playerInfo.Name, profit)); } if (!(allScore.Count >= 1)) @@ -95,20 +136,26 @@ protected override void AppendRoundEndText(EntityUid uid, AdventureRuleComponent relayText += '\n'; var highScore = allScore.OrderByDescending(h => h.Item2).ToList(); - for (var i = 0; i < 10 && i < highScore.Count; i++) + for (var i = 0; i < 10 && highScore.Count > 0; i++) { - relayText += $"{highScore.First().Item1} {profitText} {highScore.First().Item2} Spesos"; + if (highScore.First().Item2 < 0) + break; + var profitText = Loc.GetString("adventure-mode-top-profit", ("amount", BankSystemExtensions.ToSpesoString(highScore.First().Item2))); + relayText += $"{highScore.First().Item1} {profitText}"; relayText += '\n'; - highScore.Remove(highScore.First()); + highScore.RemoveAt(0); } relayText += Loc.GetString("adventure-list-low"); relayText += '\n'; highScore.Reverse(); - for (var i = 0; i < 10 && i < highScore.Count; i++) + for (var i = 0; i < 10 && highScore.Count > 0; i++) { - relayText += $"{highScore.First().Item1} {lossText} {highScore.First().Item2} Spesos"; + if (highScore.First().Item2 > 0) + break; + var lossText = Loc.GetString("adventure-mode-top-loss", ("amount", BankSystemExtensions.ToSpesoString(-highScore.First().Item2))); + relayText += $"{highScore.First().Item1} {lossText}"; relayText += '\n'; - highScore.Remove(highScore.First()); + highScore.RemoveAt(0); } ReportRound(relayText); } @@ -117,11 +164,33 @@ private void OnPlayerSpawningEvent(PlayerSpawnCompleteEvent ev) { if (ev.Player.AttachedEntity is { Valid: true } mobUid) { - _players.Add((mobUid, ev.Profile.BankBalance)); EnsureComp(mobUid); + + if (!_players.ContainsKey(mobUid)) + _players[mobUid] = new PlayerRoundBankInformation(ev.Profile.BankBalance, MetaData(mobUid).EntityName, ev.Player.UserId); + } + } + + private void OnPlayerDetachedEvent(PlayerDetachedEvent ev) + { + if (ev.Entity is { Valid: true } mobUid) + { + if (_players.ContainsKey(mobUid)) + { + if (_players[mobUid].UserId == ev.Player.UserId && + _bank.TryGetBalance(ev.Player, out var bankBalance)) + { + _players[mobUid].EndBalance = bankBalance; + } + } } } + private void OnRoundRestart(RoundRestartCleanupEvent ev) + { + _players.Clear(); + } + protected override void Started(EntityUid uid, AdventureRuleComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args) { _mapId = GameTicker.DefaultMap; @@ -441,7 +510,7 @@ private void AddStationCoordsToSet(Vector2 coords) _stationCoords.Add(coords); } - private async Task ReportRound(String message, int color = 0x77DDE7) + private async Task ReportRound(String message, int color = 0x77DDE7) { Logger.InfoS("discord", message); String webhookUrl = _configurationManager.GetCVar(CCVars.DiscordLeaderboardWebhook); diff --git a/Resources/Locale/en-US/_NF/adventure/adventure.ftl b/Resources/Locale/en-US/_NF/adventure/adventure.ftl index c65acd137c1..4930e8675b3 100644 --- a/Resources/Locale/en-US/_NF/adventure/adventure.ftl +++ b/Resources/Locale/en-US/_NF/adventure/adventure.ftl @@ -1,9 +1,11 @@ ## UI -adventure-list-start = NT Galactic Bank -adventure-mode-profit-text = made a total profit of: {" "} -adventure-mode-loss-text = lost a total of: {" "} -adventure-list-high = Today's Top Earners: -adventure-list-low = Today's Biggest Spenders: +adventure-list-start = [color=gold]NT Galactic Bank[/color] +adventure-mode-list-profit = made a total profit of [color=#d19e5e]{$amount}[/color]. +adventure-mode-list-loss = lost a total of [color=#659cc9]{$amount}[/color]. +adventure-mode-top-profit = made a total profit of {$amount}. +adventure-mode-top-loss = lost a total of {$amount}. +adventure-list-high = This Shift's Top Earners: +adventure-list-low = This Shift's Biggest Spenders: adventure-title = New Frontier Adventure Mode adventure-description = Join a ship crew or buy your own and explore, research, salvage, or haul your way to riches! currency = Spesos diff --git a/Resources/Locale/en-US/round-end/round-end-summary-window.ftl b/Resources/Locale/en-US/round-end/round-end-summary-window.ftl index 58d26319b32..11f88052265 100644 --- a/Resources/Locale/en-US/round-end/round-end-summary-window.ftl +++ b/Resources/Locale/en-US/round-end/round-end-summary-window.ftl @@ -2,7 +2,10 @@ round-end-summary-window-title = Round End Summary round-end-summary-window-round-end-summary-tab-title = Round Information round-end-summary-window-player-manifest-tab-title = Player Manifest round-end-summary-window-round-id-label = Round [color=white]#{$roundId}[/color] has ended. -round-end-summary-window-gamemode-name-label = The game mode was [color=white]{$gamemode}[/color]. +# Frontier +round-end-summary-window-gamemode-name-label = {""} +# round-end-summary-window-gamemode-name-label = The game mode was [color=white]{$gamemode}[/color]. +# End Frontier round-end-summary-window-duration-label = It lasted for [color=yellow]{$hours} hours, {$minutes} minutes, and {$seconds} seconds. round-end-summary-window-player-info-if-observer-text = [color=gray]{$playerOOCName}[/color] was [color=lightblue]{$playerICName}[/color], an observer. round-end-summary-window-player-info-if-not-observer-text = [color=gray]{$playerOOCName}[/color] was [color={$icNameColor}]{$playerICName}[/color] playing role of [color=orange]{$playerRole}[/color]. From ce8ce85ba0ef04862e2286897a02d2002730cc2e Mon Sep 17 00:00:00 2001 From: Whatstone Date: Fri, 18 Oct 2024 08:33:18 -0400 Subject: [PATCH 3/6] NfAdventureRuleSystem: add disconnect status --- .../_NF/GameRule/NfAdventureRuleSystem.cs | 36 +++++++++++++++---- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/Content.Server/_NF/GameRule/NfAdventureRuleSystem.cs b/Content.Server/_NF/GameRule/NfAdventureRuleSystem.cs index 6e710fb43a7..be78ea532b4 100644 --- a/Content.Server/_NF/GameRule/NfAdventureRuleSystem.cs +++ b/Content.Server/_NF/GameRule/NfAdventureRuleSystem.cs @@ -37,6 +37,8 @@ using Robust.Shared.Player; using Robust.Shared.Network; using Content.Shared.GameTicking; +using Robust.Shared.Enums; +using Robust.Server.Player; namespace Content.Server._NF.GameRule; @@ -48,6 +50,7 @@ public sealed class NfAdventureRuleSystem : GameRuleSystem(OnPlayerSpawningEvent); SubscribeLocalEvent(OnPlayerDetachedEvent); SubscribeLocalEvent(OnRoundRestart); + _playerManager.PlayerStatusChanged += PlayerManagerOnPlayerStatusChanged; } protected override void AppendRoundEndText(EntityUid uid, AdventureRuleComponent component, GameRuleComponent gameRule, ref RoundEndTextAppendEvent ev) @@ -145,6 +149,7 @@ protected override void AppendRoundEndText(EntityUid uid, AdventureRuleComponent relayText += '\n'; highScore.RemoveAt(0); } + relayText += '\n'; // Extra line separating the relayText += Loc.GetString("adventure-list-low"); relayText += '\n'; highScore.Reverse(); @@ -173,15 +178,32 @@ private void OnPlayerSpawningEvent(PlayerSpawnCompleteEvent ev) private void OnPlayerDetachedEvent(PlayerDetachedEvent ev) { - if (ev.Entity is { Valid: true } mobUid) + if (ev.Entity is not { Valid: true } mobUid) + return; + + if (_players.ContainsKey(mobUid)) { - if (_players.ContainsKey(mobUid)) + if (_players[mobUid].UserId == ev.Player.UserId && + _bank.TryGetBalance(ev.Player, out var bankBalance)) { - if (_players[mobUid].UserId == ev.Player.UserId && - _bank.TryGetBalance(ev.Player, out var bankBalance)) - { - _players[mobUid].EndBalance = bankBalance; - } + _players[mobUid].EndBalance = bankBalance; + } + } + } + + private void PlayerManagerOnPlayerStatusChanged(object? _, SessionStatusEventArgs e) + { + // Treat all disconnections as being possibly final. + if (e.NewStatus != SessionStatus.Disconnected || + e.Session.AttachedEntity == null) + return; + + var mobUid = e.Session.AttachedEntity.Value; + if (_players.ContainsKey(mobUid)) + { + if (_bank.TryGetBalance(e.Session, out var bankBalance)) + { + _players[mobUid].EndBalance = bankBalance; } } } From f3c35a977be8a0e8cd332481cce4e762f39ab9c1 Mon Sep 17 00:00:00 2001 From: Whatstone Date: Fri, 18 Oct 2024 08:58:01 -0400 Subject: [PATCH 4/6] Remove unused bank events, comment direct access --- Content.Server/_NF/Bank/BankEvents.cs | 19 ------------------- .../_NF/GameRule/NfAdventureRuleSystem.cs | 1 + 2 files changed, 1 insertion(+), 19 deletions(-) delete mode 100644 Content.Server/_NF/Bank/BankEvents.cs diff --git a/Content.Server/_NF/Bank/BankEvents.cs b/Content.Server/_NF/Bank/BankEvents.cs deleted file mode 100644 index cfbc0d4e5cf..00000000000 --- a/Content.Server/_NF/Bank/BankEvents.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace Content.Server.Bank; - -public sealed class BankAccountAddedEvent : EntityEventArgs -{ - public EntityUid Entity; - public BankAccountAddedEvent(EntityUid entity) - { - Entity = entity; - } -} - -public sealed class BankAccountRemovedEvent : EntityEventArgs -{ - public EntityUid Entity; - public BankAccountRemovedEvent(EntityUid entity) - { - Entity = entity; - } -} diff --git a/Content.Server/_NF/GameRule/NfAdventureRuleSystem.cs b/Content.Server/_NF/GameRule/NfAdventureRuleSystem.cs index be78ea532b4..0db6f0144d9 100644 --- a/Content.Server/_NF/GameRule/NfAdventureRuleSystem.cs +++ b/Content.Server/_NF/GameRule/NfAdventureRuleSystem.cs @@ -171,6 +171,7 @@ private void OnPlayerSpawningEvent(PlayerSpawnCompleteEvent ev) { EnsureComp(mobUid); + // Store player info with the bank balance - we have it directly, and BankSystem won't have a cache yet. if (!_players.ContainsKey(mobUid)) _players[mobUid] = new PlayerRoundBankInformation(ev.Profile.BankBalance, MetaData(mobUid).EntityName, ev.Player.UserId); } From 1ed5d148a6298afa7dcdac24b8d4a01fd5686066 Mon Sep 17 00:00:00 2001 From: Whatstone Date: Fri, 18 Oct 2024 09:12:49 -0400 Subject: [PATCH 5/6] Check user ID on disconnect --- Content.Server/_NF/GameRule/NfAdventureRuleSystem.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Content.Server/_NF/GameRule/NfAdventureRuleSystem.cs b/Content.Server/_NF/GameRule/NfAdventureRuleSystem.cs index 0db6f0144d9..475fe794447 100644 --- a/Content.Server/_NF/GameRule/NfAdventureRuleSystem.cs +++ b/Content.Server/_NF/GameRule/NfAdventureRuleSystem.cs @@ -202,7 +202,8 @@ private void PlayerManagerOnPlayerStatusChanged(object? _, SessionStatusEventArg var mobUid = e.Session.AttachedEntity.Value; if (_players.ContainsKey(mobUid)) { - if (_bank.TryGetBalance(e.Session, out var bankBalance)) + if (_players[mobUid].UserId == e.Session.UserId && + _bank.TryGetBalance(e.Session, out var bankBalance)) { _players[mobUid].EndBalance = bankBalance; } From 589e19a8be21b9011af07490ee33401953e95b29 Mon Sep 17 00:00:00 2001 From: Whatstone Date: Fri, 18 Oct 2024 09:25:38 -0400 Subject: [PATCH 6/6] print user ID, not session --- Content.Server/_NF/Bank/BankSystem.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Content.Server/_NF/Bank/BankSystem.cs b/Content.Server/_NF/Bank/BankSystem.cs index 392f73e3471..7bcc1421225 100644 --- a/Content.Server/_NF/Bank/BankSystem.cs +++ b/Content.Server/_NF/Bank/BankSystem.cs @@ -244,14 +244,14 @@ public bool TryGetBalance(ICommonSession session, out int balance) { if (!_prefsManager.TryGetCachedPreferences(session.UserId, out var prefs)) { - _log.Info($"{session} has no cached prefs"); + _log.Info($"{session.UserId} has no cached prefs"); balance = 0; return false; } if (prefs.SelectedCharacter is not HumanoidCharacterProfile profile) { - _log.Info($"{session} has the wrong prefs type"); + _log.Info($"{session.UserId} has the wrong prefs type"); balance = 0; return false; }