From e608d63861b60422aef5efd62da5faa08c920c83 Mon Sep 17 00:00:00 2001
From: Spatison <137375981+Spatison@users.noreply.github.com>
Date: Thu, 12 Sep 2024 23:47:30 +0300
Subject: [PATCH 1/7] add: respawn button
---
Content.Client/Ghost/GhostSystem.cs | 6 +
.../Systems/Ghost/GhostUIController.cs | 7 ++
.../Systems/Ghost/Widgets/GhostGui.xaml | 1 +
.../Systems/Ghost/Widgets/GhostGui.xaml.cs | 2 +
.../GameTicking/GameTicker.GamePreset.cs | 8 ++
.../GameTicking/GameTicker.Spawning.cs | 81 +++++++++++++
.../_White/Ghost/GhostReturnToRoundSystem.cs | 108 ++++++++++++++++++
Content.Shared/Ghost/SharedGhostSystem.cs | 5 +
Content.Shared/_White/CVars.cs | 10 +-
.../Locale/en-US/_white/ghost/ghost-gui.ftl | 1 +
.../en-US/_white/ghost/ghost-respawn.ftl | 14 +++
.../Locale/ru-RU/_white/ghost/ghost-gui.ftl | 1 +
.../ru-RU/_white/ghost/ghost-respawn.ftl | 15 +++
13 files changed, 258 insertions(+), 1 deletion(-)
create mode 100644 Content.Server/_White/Ghost/GhostReturnToRoundSystem.cs
create mode 100644 Resources/Locale/en-US/_white/ghost/ghost-gui.ftl
create mode 100644 Resources/Locale/en-US/_white/ghost/ghost-respawn.ftl
create mode 100644 Resources/Locale/ru-RU/_white/ghost/ghost-gui.ftl
create mode 100644 Resources/Locale/ru-RU/_white/ghost/ghost-respawn.ftl
diff --git a/Content.Client/Ghost/GhostSystem.cs b/Content.Client/Ghost/GhostSystem.cs
index c42e7cd0e0..4bc6ba4c87 100644
--- a/Content.Client/Ghost/GhostSystem.cs
+++ b/Content.Client/Ghost/GhostSystem.cs
@@ -181,5 +181,11 @@ public void ToggleGhostVisibility()
{
GhostVisibility = !GhostVisibility;
}
+
+ public void ReturnToRound() // WD EDIT
+ {
+ var msg = new GhostReturnToRoundRequest();
+ RaiseNetworkEvent(msg);
+ }
}
}
diff --git a/Content.Client/UserInterface/Systems/Ghost/GhostUIController.cs b/Content.Client/UserInterface/Systems/Ghost/GhostUIController.cs
index 12d6c65953..3834b35fe7 100644
--- a/Content.Client/UserInterface/Systems/Ghost/GhostUIController.cs
+++ b/Content.Client/UserInterface/Systems/Ghost/GhostUIController.cs
@@ -120,6 +120,7 @@ public void LoadGui()
Gui.ReturnToBodyPressed += ReturnToBody;
Gui.GhostRolesPressed += GhostRolesPressed;
Gui.TargetWindow.WarpClicked += OnWarpClicked;
+ Gui.ReturnToRoundPressed += ReturnToRound; // WD EDIT
UpdateGui();
}
@@ -133,6 +134,7 @@ public void UnloadGui()
Gui.ReturnToBodyPressed -= ReturnToBody;
Gui.GhostRolesPressed -= GhostRolesPressed;
Gui.TargetWindow.WarpClicked -= OnWarpClicked;
+ Gui.ReturnToRoundPressed -= ReturnToRound; // WD EDIT
Gui.Hide();
}
@@ -142,6 +144,11 @@ private void ReturnToBody()
_system?.ReturnToBody();
}
+ private void ReturnToRound() // WD EDIT
+ {
+ _system?.ReturnToRound();
+ }
+
private void RequestWarps()
{
_system?.RequestWarps();
diff --git a/Content.Client/UserInterface/Systems/Ghost/Widgets/GhostGui.xaml b/Content.Client/UserInterface/Systems/Ghost/Widgets/GhostGui.xaml
index 0f65debb4e..7e1760aa5e 100644
--- a/Content.Client/UserInterface/Systems/Ghost/Widgets/GhostGui.xaml
+++ b/Content.Client/UserInterface/Systems/Ghost/Widgets/GhostGui.xaml
@@ -5,5 +5,6 @@
+
diff --git a/Content.Client/UserInterface/Systems/Ghost/Widgets/GhostGui.xaml.cs b/Content.Client/UserInterface/Systems/Ghost/Widgets/GhostGui.xaml.cs
index 18c1d545a7..ee3f8005a9 100644
--- a/Content.Client/UserInterface/Systems/Ghost/Widgets/GhostGui.xaml.cs
+++ b/Content.Client/UserInterface/Systems/Ghost/Widgets/GhostGui.xaml.cs
@@ -14,6 +14,7 @@ public sealed partial class GhostGui : UIWidget
public event Action? RequestWarpsPressed;
public event Action? ReturnToBodyPressed;
public event Action? GhostRolesPressed;
+ public event Action? ReturnToRoundPressed; // WD EDIT
public GhostGui()
{
@@ -26,6 +27,7 @@ public GhostGui()
GhostWarpButton.OnPressed += _ => RequestWarpsPressed?.Invoke();
ReturnToBodyButton.OnPressed += _ => ReturnToBodyPressed?.Invoke();
GhostRolesButton.OnPressed += _ => GhostRolesPressed?.Invoke();
+ ReturnToRound.OnPressed += _ => ReturnToRoundPressed?.Invoke(); // WD EDIT
}
public void Hide()
diff --git a/Content.Server/GameTicking/GameTicker.GamePreset.cs b/Content.Server/GameTicking/GameTicker.GamePreset.cs
index b97a16ab99..5e2c7745e1 100644
--- a/Content.Server/GameTicking/GameTicker.GamePreset.cs
+++ b/Content.Server/GameTicking/GameTicker.GamePreset.cs
@@ -1,6 +1,7 @@
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Threading.Tasks;
+using Content.Server._White.Ghost;
using Content.Server.GameTicking.Presets;
using Content.Server.Maps;
using Content.Shared.CCVar;
@@ -21,6 +22,7 @@ namespace Content.Server.GameTicking
public sealed partial class GameTicker
{
[Dependency] private readonly MobThresholdSystem _mobThresholdSystem = default!;
+ [Dependency] private readonly GhostReturnToRoundSystem _ghostReturnToRound = default!; // WD EDIT
public const float PresetFailedCooldownIncrease = 30f;
@@ -303,6 +305,12 @@ public bool OnGhostAttempt(EntityUid mindId, bool canReturnGlobal, bool viaComma
_mind.Visit(mindId, ghost, mind);
else
_mind.TransferTo(mindId, ghost, mind: mind);
+
+ // WD EDIT START
+ var userId = mind.Session!.UserId;
+ if (!_ghostReturnToRound.DeathTime.TryGetValue(userId, out _))
+ _ghostReturnToRound.DeathTime[userId] = _gameTiming.CurTime;
+ // WD EDIT END
return true;
}
diff --git a/Content.Server/GameTicking/GameTicker.Spawning.cs b/Content.Server/GameTicking/GameTicker.Spawning.cs
index b28521c20a..f8dec2032d 100644
--- a/Content.Server/GameTicking/GameTicker.Spawning.cs
+++ b/Content.Server/GameTicking/GameTicker.Spawning.cs
@@ -7,7 +7,9 @@
using Content.Server.Speech.Components;
using Content.Server.Station.Components;
using Content.Shared.CCVar;
+using Content.Shared.Chat;
using Content.Shared.Database;
+using Content.Shared.Mind;
using Content.Shared.Players;
using Content.Shared.Preferences;
using Content.Shared.Roles;
@@ -154,6 +156,66 @@ private void SpawnPlayer(ICommonSession player, HumanoidCharacterProfile charact
return;
}
+ //WD EDIT START
+ //Ghost system return to round, check for whether the character isn't the same.
+ if (lateJoin && !_adminManager.IsAdmin(player))
+ {
+ var sameChar = false;
+ var checkAvoid = false;
+
+ var allPlayerMinds = EntityQuery()
+ .Where(mind => mind.OriginalOwnerUserId == player.UserId);
+
+ foreach (var mind in allPlayerMinds)
+ {
+ if (mind.CharacterName == character.Name)
+ {
+ sameChar = true;
+ break;
+ }
+
+ if (mind.CharacterName != null)
+ {
+ var similarity = CalculateStringSimilarity(mind.CharacterName, character.Name);
+
+ switch (similarity)
+ {
+ case >= 85f:
+ {
+ _chatManager.SendAdminAlert(Loc.GetString("ghost-respawn-log-character-almost-same",
+ ("player", player.Name), ("try", false), ("oldName", mind.CharacterName), ("newName", character.Name)));
+
+ checkAvoid = true;
+ sameChar = true;
+
+ break;
+ }
+ case >= 50f:
+ {
+ _chatManager.SendAdminAlert(Loc.GetString("ghost-respawn-log-character-almost-same",
+ ("player", player.Name), ("try", true), ("oldName", mind.CharacterName), ("newName", character.Name)));
+
+ break;
+ }
+ }
+ }
+ }
+
+ if (sameChar)
+ {
+ var message = checkAvoid
+ ? Loc.GetString("ghost-respawn-same-character-slightly-changed-name")
+ : Loc.GetString("ghost-respawn-same-character");
+ var wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", message));
+
+ _chatManager.ChatMessageToOne(ChatChannel.Server, message, wrappedMessage,
+ default, false, player.Channel, Color.Red);
+
+ return;
+ }
+ }
+ //WD EDIT END
+
// We raise this event to allow other systems to handle spawning this player themselves. (e.g. late-join wizard, etc)
var bev = new PlayerBeforeSpawnEvent(player, character, jobId, lateJoin, station);
RaiseLocalEvent(bev);
@@ -346,6 +408,25 @@ public void SpawnObserver(ICommonSession player)
_adminLogger.Add(LogType.LateJoin, LogImpact.Low, $"{player.Name} late joined the round as an Observer with {ToPrettyString(ghost):entity}.");
}
+ //WD EDIT START
+ private float CalculateStringSimilarity(string str1, string str2)
+ {
+ var minLength = Math.Min(str1.Length, str2.Length);
+ var matchingCharacters = 0;
+
+ for (var i = 0; i < minLength; i++)
+ {
+ if (str1[i] == str2[i])
+ matchingCharacters++;
+ }
+
+ float maxLength = Math.Max(str1.Length, str2.Length);
+ var similarityPercentage = (matchingCharacters / maxLength) * 100;
+
+ return similarityPercentage;
+ }
+ //WD EDIT END
+
#region Mob Spawning Helpers
private EntityUid SpawnObserverMob()
{
diff --git a/Content.Server/_White/Ghost/GhostReturnToRoundSystem.cs b/Content.Server/_White/Ghost/GhostReturnToRoundSystem.cs
new file mode 100644
index 0000000000..7f30a98a59
--- /dev/null
+++ b/Content.Server/_White/Ghost/GhostReturnToRoundSystem.cs
@@ -0,0 +1,108 @@
+using Content.Server.Administration.Logs;
+using Content.Server.Chat.Managers;
+using Content.Server.GameTicking;
+using Content.Shared._White;
+using Content.Shared.Database;
+using Content.Shared.GameTicking;
+using Content.Shared.Ghost;
+using Robust.Server.Player;
+using Robust.Shared.Configuration;
+using Robust.Shared.Network;
+using Robust.Shared.Timing;
+
+namespace Content.Server._White.Ghost;
+
+public sealed class GhostReturnToRoundSystem : EntitySystem
+{
+ [Dependency] private readonly IChatManager _chatManager = default!;
+ [Dependency] private readonly IAdminLogManager _adminLogger = default!;
+ [Dependency] private readonly IPlayerManager _playerManager = default!;
+ [Dependency] private readonly IGameTiming _gameTiming = default!;
+
+ public readonly Dictionary DeathTime = new();
+
+ public override void Initialize()
+ {
+ SubscribeNetworkEvent(OnGhostReturnToRoundRequest);
+ SubscribeLocalEvent(ResetDeathTimes);
+ }
+
+ private void OnGhostReturnToRoundRequest(GhostReturnToRoundRequest msg, EntitySessionEventArgs args)
+ {
+ var cfg = IoCManager.Resolve();
+ var maxPlayers = cfg.GetCVar(WhiteCVars.GhostRespawnMaxPlayers);
+ var connectedClient = args.SenderSession.ConnectedClient;
+ if (_playerManager.PlayerCount >= maxPlayers)
+ {
+ var message = Loc.GetString("ghost-respawn-max-players", ("players", maxPlayers));
+ var wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", message));
+ _chatManager.ChatMessageToOne(Shared.Chat.ChatChannel.Server,
+ message,
+ wrappedMessage,
+ default,
+ false,
+ connectedClient,
+ Color.Red);
+ return;
+ }
+
+ var userId = args.SenderSession.UserId;
+ if (!DeathTime.TryGetValue(userId, out var deathTime))
+ {
+ var message = Loc.GetString("ghost-respawn-bug");
+ var wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", message));
+ _chatManager.ChatMessageToOne(Shared.Chat.ChatChannel.Server,
+ message,
+ wrappedMessage,
+ default,
+ false,
+ connectedClient,
+ Color.Red);
+ DeathTime[userId] = _gameTiming.CurTime;
+ return;
+ }
+
+ var timeUntilRespawn = (double) cfg.GetCVar(WhiteCVars.GhostRespawnTime);
+ var timePast = (_gameTiming.CurTime - deathTime).TotalMinutes;
+ if (timePast >= timeUntilRespawn)
+ {
+ var ticker = Get();
+ var playerMgr = IoCManager.Resolve();
+ playerMgr.TryGetSessionById(userId, out var targetPlayer);
+
+ if (targetPlayer != null)
+ ticker.Respawn(targetPlayer);
+ DeathTime.Remove(userId);
+
+ _adminLogger.Add(LogType.Mind, LogImpact.Medium, $"{Loc.GetString("ghost-respawn-log-return-to-lobby", ("userName", connectedClient.UserName))}");
+
+ var message = Loc.GetString("ghost-respawn-window-rules-footer");
+ var wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", message));
+ _chatManager.ChatMessageToOne(Shared.Chat.ChatChannel.Server,
+ message,
+ wrappedMessage,
+ default,
+ false,
+ connectedClient,
+ Color.Red);
+
+ }
+ else
+ {
+ var message = Loc.GetString("ghost-respawn-time-left", ("time", (int) (timeUntilRespawn - timePast)));
+ var wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", message));
+ _chatManager.ChatMessageToOne(Shared.Chat.ChatChannel.Server,
+ message,
+ wrappedMessage,
+ default,
+ false,
+ connectedClient,
+ Color.Red);
+ }
+ }
+
+ private void ResetDeathTimes(RoundRestartCleanupEvent ev)
+ {
+ DeathTime.Clear();
+ }
+}
diff --git a/Content.Shared/Ghost/SharedGhostSystem.cs b/Content.Shared/Ghost/SharedGhostSystem.cs
index 24da2f144f..ede37bda2d 100644
--- a/Content.Shared/Ghost/SharedGhostSystem.cs
+++ b/Content.Shared/Ghost/SharedGhostSystem.cs
@@ -148,4 +148,9 @@ public GhostUpdateGhostRoleCountEvent(int availableGhostRoleCount)
AvailableGhostRoles = availableGhostRoleCount;
}
}
+
+ // WD EDIT START
+ [Serializable, NetSerializable]
+ public sealed class GhostReturnToRoundRequest : EntityEventArgs;
+ // WD EDIT END
}
diff --git a/Content.Shared/_White/CVars.cs b/Content.Shared/_White/CVars.cs
index 0b527efe1c..cff7de2535 100644
--- a/Content.Shared/_White/CVars.cs
+++ b/Content.Shared/_White/CVars.cs
@@ -12,7 +12,7 @@ public sealed class WhiteCVars
public static readonly CVarDef AspectChance =
CVarDef.Create("aspects.chance", 0.1d, CVar.SERVERONLY);
-
+
#endregion
#region Keybind
@@ -31,4 +31,12 @@ public static readonly CVarDef
ServerCulture = CVarDef.Create("white.culture", "ru-RU", CVar.REPLICATED | CVar.SERVER);
#endregion
+
+ #region GhostRespawn
+ public static readonly CVarDef GhostRespawnTime =
+ CVarDef.Create("ghost.respawn_time", 15f, CVar.SERVERONLY);
+
+ public static readonly CVarDef GhostRespawnMaxPlayers =
+ CVarDef.Create("ghost.respawn_max_players", 40, CVar.SERVERONLY);
+ #endregion
}
diff --git a/Resources/Locale/en-US/_white/ghost/ghost-gui.ftl b/Resources/Locale/en-US/_white/ghost/ghost-gui.ftl
new file mode 100644
index 0000000000..ce9084d21f
--- /dev/null
+++ b/Resources/Locale/en-US/_white/ghost/ghost-gui.ftl
@@ -0,0 +1 @@
+ghost-gui-return-to-round-button = Вернуться в раунд
\ No newline at end of file
diff --git a/Resources/Locale/en-US/_white/ghost/ghost-respawn.ftl b/Resources/Locale/en-US/_white/ghost/ghost-respawn.ftl
new file mode 100644
index 0000000000..efdcf08f0c
--- /dev/null
+++ b/Resources/Locale/en-US/_white/ghost/ghost-respawn.ftl
@@ -0,0 +1,14 @@
+ghost-respawn-time-left = Before the opportunity to return to the round { $time ->
+ [one] { $time } minute
+ *[other] { $time } minutes}.
+ghost-respawn-max-players = The function is not available, there should be fewer players on the server { $players }.
+ghost-respawn-window-title = Rules for returning to the round
+ghost-respawn-window-rules-footer = By using this feature, you [color=#ff7700]agree[/color] [color=#ff0000]not to transfer[/color] the knowledge of your past character to a new one. For violation of the clause specified here, [color=#ff0000]a ban in the amount of 3 days or more follows[/color].
+ghost-respawn-bug = There is no time of death. The standard value is set.
+ghost-respawn-same-character = You cannot enter the round for the same character. Change it in the character settings.
+
+ghost-respawn-log-character-almost-same = Player { $player } { $try ->
+ [true] join
+ *[false] tried to join
+} in the round after the respawn with a similar name. Past name: { $oldName }, current: { $newName }.
+ghost-respawn-log-return-to-lobby = { $userName } returned to the lobby.
\ No newline at end of file
diff --git a/Resources/Locale/ru-RU/_white/ghost/ghost-gui.ftl b/Resources/Locale/ru-RU/_white/ghost/ghost-gui.ftl
new file mode 100644
index 0000000000..9a89f477a6
--- /dev/null
+++ b/Resources/Locale/ru-RU/_white/ghost/ghost-gui.ftl
@@ -0,0 +1 @@
+ghost-gui-return-to-round-button = Return to round
\ No newline at end of file
diff --git a/Resources/Locale/ru-RU/_white/ghost/ghost-respawn.ftl b/Resources/Locale/ru-RU/_white/ghost/ghost-respawn.ftl
new file mode 100644
index 0000000000..f95e8d94c1
--- /dev/null
+++ b/Resources/Locale/ru-RU/_white/ghost/ghost-respawn.ftl
@@ -0,0 +1,15 @@
+ghost-respawn-time-left = До возможности вернуться в раунд { $time ->
+ [one] { $time } минута
+ [few] { $time } минуты
+ *[other] { $time } минут}.
+ghost-respawn-max-players = Функция недоступна, игроков на сервере должно быть меньше { $players }.
+ghost-respawn-window-title = Правила возвращения в раунд
+ghost-respawn-window-rules-footer = Пользуясь это функцией, вы [color=#ff7700]обязуетесь[/color] [color=#ff0000]не переносить[/color] знания своего прошлого персонажа в нового. За нарушение пункта, указанного здесь, следует [color=#ff0000]бан в размере от 3-ех дней[/color].
+ghost-respawn-bug = Нет времени смерти. Установлено стандартное значение.
+ghost-respawn-same-character = Нельзя заходить в раунд за того же персонажа. Поменяйте его в настройках персонажей.
+
+ghost-respawn-log-character-almost-same = Игрок { $player } { $try ->
+ [true] зашёл
+ *[false] попытался зайти
+} в раунд после возвращения в лобби с похожим именем. Прошлое имя: { $oldName }, текущее: { $newName }.
+ghost-respawn-log-return-to-lobby = { $userName } вернулся в лобби.
\ No newline at end of file
From ec107d5d7804bf911fa66eac10614672433cbe56 Mon Sep 17 00:00:00 2001
From: Spatison <137375981+Spatison@users.noreply.github.com>
Date: Thu, 12 Sep 2024 23:51:36 +0300
Subject: [PATCH 2/7] fix: Loc
---
Resources/Locale/en-US/_white/ghost/ghost-gui.ftl | 2 +-
Resources/Locale/ru-RU/_white/ghost/ghost-gui.ftl | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/Resources/Locale/en-US/_white/ghost/ghost-gui.ftl b/Resources/Locale/en-US/_white/ghost/ghost-gui.ftl
index ce9084d21f..9a89f477a6 100644
--- a/Resources/Locale/en-US/_white/ghost/ghost-gui.ftl
+++ b/Resources/Locale/en-US/_white/ghost/ghost-gui.ftl
@@ -1 +1 @@
-ghost-gui-return-to-round-button = Вернуться в раунд
\ No newline at end of file
+ghost-gui-return-to-round-button = Return to round
\ No newline at end of file
diff --git a/Resources/Locale/ru-RU/_white/ghost/ghost-gui.ftl b/Resources/Locale/ru-RU/_white/ghost/ghost-gui.ftl
index 9a89f477a6..ce9084d21f 100644
--- a/Resources/Locale/ru-RU/_white/ghost/ghost-gui.ftl
+++ b/Resources/Locale/ru-RU/_white/ghost/ghost-gui.ftl
@@ -1 +1 @@
-ghost-gui-return-to-round-button = Return to round
\ No newline at end of file
+ghost-gui-return-to-round-button = Вернуться в раунд
\ No newline at end of file
From fbbb092bb499041c6d03349d47cac2bd02c09721 Mon Sep 17 00:00:00 2001
From: Spatison <137375981+Spatison@users.noreply.github.com>
Date: Fri, 13 Sep 2024 00:16:03 +0300
Subject: [PATCH 3/7] fix
---
Resources/Locale/en-US/_white/ghost/ghost-respawn.ftl | 8 +++++---
Resources/Locale/ru-RU/_white/ghost/ghost-respawn.ftl | 10 ++++++----
2 files changed, 11 insertions(+), 7 deletions(-)
diff --git a/Resources/Locale/en-US/_white/ghost/ghost-respawn.ftl b/Resources/Locale/en-US/_white/ghost/ghost-respawn.ftl
index efdcf08f0c..58356804bb 100644
--- a/Resources/Locale/en-US/_white/ghost/ghost-respawn.ftl
+++ b/Resources/Locale/en-US/_white/ghost/ghost-respawn.ftl
@@ -1,6 +1,8 @@
-ghost-respawn-time-left = Before the opportunity to return to the round { $time ->
- [one] { $time } minute
- *[other] { $time } minutes}.
+ghost-respawn-time-left = Before the opportunity to return to the round
+ { $time ->
+ [one] { $time } minute
+ *[other] { $time } minutes
+ }.
ghost-respawn-max-players = The function is not available, there should be fewer players on the server { $players }.
ghost-respawn-window-title = Rules for returning to the round
ghost-respawn-window-rules-footer = By using this feature, you [color=#ff7700]agree[/color] [color=#ff0000]not to transfer[/color] the knowledge of your past character to a new one. For violation of the clause specified here, [color=#ff0000]a ban in the amount of 3 days or more follows[/color].
diff --git a/Resources/Locale/ru-RU/_white/ghost/ghost-respawn.ftl b/Resources/Locale/ru-RU/_white/ghost/ghost-respawn.ftl
index f95e8d94c1..53dbdaf172 100644
--- a/Resources/Locale/ru-RU/_white/ghost/ghost-respawn.ftl
+++ b/Resources/Locale/ru-RU/_white/ghost/ghost-respawn.ftl
@@ -1,7 +1,9 @@
-ghost-respawn-time-left = До возможности вернуться в раунд { $time ->
- [one] { $time } минута
- [few] { $time } минуты
- *[other] { $time } минут}.
+ghost-respawn-time-left = До возможности вернуться в раунд
+ { $time ->
+ [one] { $time } минута
+ [few] { $time } минуты
+ *[other] { $time } минут
+ }.
ghost-respawn-max-players = Функция недоступна, игроков на сервере должно быть меньше { $players }.
ghost-respawn-window-title = Правила возвращения в раунд
ghost-respawn-window-rules-footer = Пользуясь это функцией, вы [color=#ff7700]обязуетесь[/color] [color=#ff0000]не переносить[/color] знания своего прошлого персонажа в нового. За нарушение пункта, указанного здесь, следует [color=#ff0000]бан в размере от 3-ех дней[/color].
From 5734b49e652a27322273c0ae3d3489bcb61b8e70 Mon Sep 17 00:00:00 2001
From: Spatison <137375981+Spatison@users.noreply.github.com>
Date: Fri, 13 Sep 2024 20:00:15 +0300
Subject: [PATCH 4/7] fix
---
.../Locale/en-US/_white/ghost/ghost-respawn.ftl | 8 ++++----
.../Locale/ru-RU/_white/ghost/ghost-respawn.ftl | 10 +++++-----
Resources/Locale/ru-RU/ghost/ghost-gui.ftl | 16 +---------------
3 files changed, 10 insertions(+), 24 deletions(-)
diff --git a/Resources/Locale/en-US/_white/ghost/ghost-respawn.ftl b/Resources/Locale/en-US/_white/ghost/ghost-respawn.ftl
index 58356804bb..e45fc16c74 100644
--- a/Resources/Locale/en-US/_white/ghost/ghost-respawn.ftl
+++ b/Resources/Locale/en-US/_white/ghost/ghost-respawn.ftl
@@ -1,8 +1,8 @@
-ghost-respawn-time-left = Before the opportunity to return to the round
+ghost-respawn-time-left = Before the opportunity to return to the round { $time }
{ $time ->
- [one] { $time } minute
- *[other] { $time } minutes
- }.
+ [one] minute
+ *[other] minutes
+ }
ghost-respawn-max-players = The function is not available, there should be fewer players on the server { $players }.
ghost-respawn-window-title = Rules for returning to the round
ghost-respawn-window-rules-footer = By using this feature, you [color=#ff7700]agree[/color] [color=#ff0000]not to transfer[/color] the knowledge of your past character to a new one. For violation of the clause specified here, [color=#ff0000]a ban in the amount of 3 days or more follows[/color].
diff --git a/Resources/Locale/ru-RU/_white/ghost/ghost-respawn.ftl b/Resources/Locale/ru-RU/_white/ghost/ghost-respawn.ftl
index 53dbdaf172..402a06f726 100644
--- a/Resources/Locale/ru-RU/_white/ghost/ghost-respawn.ftl
+++ b/Resources/Locale/ru-RU/_white/ghost/ghost-respawn.ftl
@@ -1,9 +1,9 @@
-ghost-respawn-time-left = До возможности вернуться в раунд
+ghost-respawn-time-left = До возможности вернуться в раунд { $time }
{ $time ->
- [one] { $time } минута
- [few] { $time } минуты
- *[other] { $time } минут
- }.
+ [one] минута
+ [few] минуты
+ *[other] минут
+ }
ghost-respawn-max-players = Функция недоступна, игроков на сервере должно быть меньше { $players }.
ghost-respawn-window-title = Правила возвращения в раунд
ghost-respawn-window-rules-footer = Пользуясь это функцией, вы [color=#ff7700]обязуетесь[/color] [color=#ff0000]не переносить[/color] знания своего прошлого персонажа в нового. За нарушение пункта, указанного здесь, следует [color=#ff0000]бан в размере от 3-ех дней[/color].
diff --git a/Resources/Locale/ru-RU/ghost/ghost-gui.ftl b/Resources/Locale/ru-RU/ghost/ghost-gui.ftl
index 074860a264..fcbde2e178 100644
--- a/Resources/Locale/ru-RU/ghost/ghost-gui.ftl
+++ b/Resources/Locale/ru-RU/ghost/ghost-gui.ftl
@@ -30,18 +30,4 @@ ghost-roles-window-no-roles-available-label = В настоящее время
ghost-return-to-body-title = Вернуться в тело
ghost-return-to-body-text = Вы возрождаетесь! Вернуться в свое тело?
-ghost-roles-window-rules-footer = Кнопка станет доступна через { $time } секунд (эта задержка нужна, чтобы убедиться, что вы прочитали правила).
-
-ghost-respawn-time-left = Минут осталось до возможности вернуться в раунд - { $time }.
-ghost-respawn-max-players = Функция недоступна, игроков на сервере должно быть меньше { $players }.
-ghost-respawn-window-title = Правила возвращения в раунд
-ghost-respawn-window-request-button-timer = Принять ({ $time }сек.)
-ghost-respawn-window-request-button = Принять
-ghost-respawn-window-rules-footer = Пользуясь это функцией, вы [color=#ff7700]обязуетесь[/color] [color=#ff0000]не переносить[/color] знания своего прошлого персонажа в нового, [color=#ff0000]не метамстить[/color]. Каждый новый персонаж - [color=#ff7700]чистый уникальный лист[/color], который никак не связан с предыдущим. Поэтому не забудьте [color=#ff7700]поменять персонажа[/color] перед заходом, а также помните, что за нарушение пункта, указанного здесь, следует [color=#ff0000]бан в размере от 3ех дней[/color].
-ghost-respawn-bug = Нет времени смерти. Установлено стандартное значение.
-ghost-respawn-same-character = Нельзя заходить в раунд за того же персонажа. Поменяйте его в настройках персонажей.
-ghost-respawn-character-almost-same = Игрок { $player } { $try ->
- [true] зашёл
- *[false] попытался зайти
-} в раунд после респауна с похожим именем. Прошлое имя: { $oldName }, текущее: { $newName }.
-ghost-respawn-same-character-slightly-changed-name = Попытка обойти запрет входа в раунд тем же персонажем. Ваши действия будут переданы администрации!
+ghost-roles-window-rules-footer = Кнопка станет доступна через { $time } секунд (эта задержка нужна, чтобы убедиться, что вы прочитали правила).
\ No newline at end of file
From 1f84c4b858774a56ff16adbce9c21d362ab8e04e Mon Sep 17 00:00:00 2001
From: Spatison <137375981+Spatison@users.noreply.github.com>
Date: Fri, 13 Sep 2024 22:42:21 +0300
Subject: [PATCH 5/7] fix
---
Content.Server/GameTicking/GameTicker.GamePreset.cs | 3 +++
1 file changed, 3 insertions(+)
diff --git a/Content.Server/GameTicking/GameTicker.GamePreset.cs b/Content.Server/GameTicking/GameTicker.GamePreset.cs
index 5e2c7745e1..e18c3e7128 100644
--- a/Content.Server/GameTicking/GameTicker.GamePreset.cs
+++ b/Content.Server/GameTicking/GameTicker.GamePreset.cs
@@ -307,6 +307,9 @@ public bool OnGhostAttempt(EntityUid mindId, bool canReturnGlobal, bool viaComma
_mind.TransferTo(mindId, ghost, mind: mind);
// WD EDIT START
+ if (mind.Session == null)
+ return true;
+
var userId = mind.Session!.UserId;
if (!_ghostReturnToRound.DeathTime.TryGetValue(userId, out _))
_ghostReturnToRound.DeathTime[userId] = _gameTiming.CurTime;
From 67c6eb6d377de60df671227aa9120fa7c2bdb4c2 Mon Sep 17 00:00:00 2001
From: Spatison <137375981+Spatison@users.noreply.github.com>
Date: Tue, 17 Sep 2024 00:49:24 +0300
Subject: [PATCH 6/7] fix
---
.../GameTicking/GameTicker.GamePreset.cs | 8 --
.../GameTicking/GameTicker.Spawning.cs | 101 +++++++++---------
.../_White/Ghost/GhostReturnToRoundSystem.cs | 89 ++++++---------
Content.Shared/_White/CVars.cs | 4 +-
.../en-US/_white/ghost/ghost-respawn.ftl | 1 -
.../ru-RU/_white/ghost/ghost-respawn.ftl | 1 -
6 files changed, 82 insertions(+), 122 deletions(-)
diff --git a/Content.Server/GameTicking/GameTicker.GamePreset.cs b/Content.Server/GameTicking/GameTicker.GamePreset.cs
index e18c3e7128..8ddd0ba180 100644
--- a/Content.Server/GameTicking/GameTicker.GamePreset.cs
+++ b/Content.Server/GameTicking/GameTicker.GamePreset.cs
@@ -306,14 +306,6 @@ public bool OnGhostAttempt(EntityUid mindId, bool canReturnGlobal, bool viaComma
else
_mind.TransferTo(mindId, ghost, mind: mind);
- // WD EDIT START
- if (mind.Session == null)
- return true;
-
- var userId = mind.Session!.UserId;
- if (!_ghostReturnToRound.DeathTime.TryGetValue(userId, out _))
- _ghostReturnToRound.DeathTime[userId] = _gameTiming.CurTime;
- // WD EDIT END
return true;
}
diff --git a/Content.Server/GameTicking/GameTicker.Spawning.cs b/Content.Server/GameTicking/GameTicker.Spawning.cs
index f8dec2032d..3d35128e08 100644
--- a/Content.Server/GameTicking/GameTicker.Spawning.cs
+++ b/Content.Server/GameTicking/GameTicker.Spawning.cs
@@ -158,61 +158,17 @@ private void SpawnPlayer(ICommonSession player, HumanoidCharacterProfile charact
//WD EDIT START
//Ghost system return to round, check for whether the character isn't the same.
- if (lateJoin && !_adminManager.IsAdmin(player))
+ if (lateJoin && !_adminManager.IsAdmin(player) && !CheckGhostReturnToRound(player, character, out var checkAvoid))
{
- var sameChar = false;
- var checkAvoid = false;
+ var message = checkAvoid
+ ? Loc.GetString("ghost-respawn-same-character-slightly-changed-name")
+ : Loc.GetString("ghost-respawn-same-character");
+ var wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", message));
- var allPlayerMinds = EntityQuery()
- .Where(mind => mind.OriginalOwnerUserId == player.UserId);
+ _chatManager.ChatMessageToOne(ChatChannel.Server, message, wrappedMessage,
+ default, false, player.Channel, Color.Red);
- foreach (var mind in allPlayerMinds)
- {
- if (mind.CharacterName == character.Name)
- {
- sameChar = true;
- break;
- }
-
- if (mind.CharacterName != null)
- {
- var similarity = CalculateStringSimilarity(mind.CharacterName, character.Name);
-
- switch (similarity)
- {
- case >= 85f:
- {
- _chatManager.SendAdminAlert(Loc.GetString("ghost-respawn-log-character-almost-same",
- ("player", player.Name), ("try", false), ("oldName", mind.CharacterName), ("newName", character.Name)));
-
- checkAvoid = true;
- sameChar = true;
-
- break;
- }
- case >= 50f:
- {
- _chatManager.SendAdminAlert(Loc.GetString("ghost-respawn-log-character-almost-same",
- ("player", player.Name), ("try", true), ("oldName", mind.CharacterName), ("newName", character.Name)));
-
- break;
- }
- }
- }
- }
-
- if (sameChar)
- {
- var message = checkAvoid
- ? Loc.GetString("ghost-respawn-same-character-slightly-changed-name")
- : Loc.GetString("ghost-respawn-same-character");
- var wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", message));
-
- _chatManager.ChatMessageToOne(ChatChannel.Server, message, wrappedMessage,
- default, false, player.Channel, Color.Red);
-
- return;
- }
+ return;
}
//WD EDIT END
@@ -409,6 +365,47 @@ public void SpawnObserver(ICommonSession player)
}
//WD EDIT START
+ private bool CheckGhostReturnToRound(ICommonSession player, HumanoidCharacterProfile character, out bool checkAvoid)
+ {
+ checkAvoid = false;
+
+ var allPlayerMinds = EntityQuery()
+ .Where(mind => mind.OriginalOwnerUserId == player.UserId);
+
+ foreach (var mind in allPlayerMinds)
+ {
+ if (mind.CharacterName == character.Name)
+ return false;
+
+ if (mind.CharacterName == null)
+ continue;
+
+ var similarity = CalculateStringSimilarity(mind.CharacterName, character.Name);
+ switch (similarity)
+ {
+ case >= 85f:
+ {
+ _chatManager.SendAdminAlert(Loc.GetString("ghost-respawn-log-character-almost-same",
+ ("player", player.Name), ("try", false), ("oldName", mind.CharacterName),
+ ("newName", character.Name)));
+ checkAvoid = true;
+
+ return false;
+ }
+ case >= 50f:
+ {
+ _chatManager.SendAdminAlert(Loc.GetString("ghost-respawn-log-character-almost-same",
+ ("player", player.Name), ("try", true), ("oldName", mind.CharacterName),
+ ("newName", character.Name)));
+
+ break;
+ }
+ }
+ }
+
+ return true;
+ }
+
private float CalculateStringSimilarity(string str1, string str2)
{
var minLength = Math.Min(str1.Length, str2.Length);
diff --git a/Content.Server/_White/Ghost/GhostReturnToRoundSystem.cs b/Content.Server/_White/Ghost/GhostReturnToRoundSystem.cs
index 7f30a98a59..e3c5a0647f 100644
--- a/Content.Server/_White/Ghost/GhostReturnToRoundSystem.cs
+++ b/Content.Server/_White/Ghost/GhostReturnToRoundSystem.cs
@@ -18,91 +18,64 @@ public sealed class GhostReturnToRoundSystem : EntitySystem
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
-
- public readonly Dictionary DeathTime = new();
+ [Dependency] private readonly IConfigurationManager _cfg = default!;
public override void Initialize()
{
SubscribeNetworkEvent(OnGhostReturnToRoundRequest);
- SubscribeLocalEvent(ResetDeathTimes);
}
private void OnGhostReturnToRoundRequest(GhostReturnToRoundRequest msg, EntitySessionEventArgs args)
{
- var cfg = IoCManager.Resolve();
- var maxPlayers = cfg.GetCVar(WhiteCVars.GhostRespawnMaxPlayers);
- var connectedClient = args.SenderSession.ConnectedClient;
- if (_playerManager.PlayerCount >= maxPlayers)
- {
- var message = Loc.GetString("ghost-respawn-max-players", ("players", maxPlayers));
- var wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", message));
- _chatManager.ChatMessageToOne(Shared.Chat.ChatChannel.Server,
- message,
- wrappedMessage,
- default,
- false,
- connectedClient,
- Color.Red);
+ var uid = args.SenderSession.AttachedEntity;
+
+ if (uid == null)
return;
- }
+ var connectedClient = args.SenderSession.ConnectedClient;
var userId = args.SenderSession.UserId;
- if (!DeathTime.TryGetValue(userId, out var deathTime))
+
+ TryGhostReturnToRound(uid.Value, connectedClient, userId, out var message, out var wrappedMessage);
+
+ _chatManager.ChatMessageToOne(Shared.Chat.ChatChannel.Server,
+ message,
+ wrappedMessage,
+ default,
+ false,
+ connectedClient,
+ Color.Red);
+ }
+
+ private void TryGhostReturnToRound(EntityUid uid, INetChannel connectedClient, NetUserId userId, out string message, out string wrappedMessage)
+ {
+ var maxPlayers = _cfg.GetCVar(WhiteCVars.GhostRespawnMaxPlayers);
+ if (_playerManager.PlayerCount >= maxPlayers)
{
- var message = Loc.GetString("ghost-respawn-bug");
- var wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", message));
- _chatManager.ChatMessageToOne(Shared.Chat.ChatChannel.Server,
- message,
- wrappedMessage,
- default,
- false,
- connectedClient,
- Color.Red);
- DeathTime[userId] = _gameTiming.CurTime;
+ message = Loc.GetString("ghost-respawn-max-players", ("players", maxPlayers));
+ wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", message));
return;
}
- var timeUntilRespawn = (double) cfg.GetCVar(WhiteCVars.GhostRespawnTime);
+ var deathTime = EnsureComp(uid).TimeOfDeath;
+ var timeUntilRespawn = _cfg.GetCVar(WhiteCVars.GhostRespawnTime);
var timePast = (_gameTiming.CurTime - deathTime).TotalMinutes;
if (timePast >= timeUntilRespawn)
{
var ticker = Get();
- var playerMgr = IoCManager.Resolve();
- playerMgr.TryGetSessionById(userId, out var targetPlayer);
+ _playerManager.TryGetSessionById(userId, out var targetPlayer);
if (targetPlayer != null)
ticker.Respawn(targetPlayer);
- DeathTime.Remove(userId);
_adminLogger.Add(LogType.Mind, LogImpact.Medium, $"{Loc.GetString("ghost-respawn-log-return-to-lobby", ("userName", connectedClient.UserName))}");
- var message = Loc.GetString("ghost-respawn-window-rules-footer");
- var wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", message));
- _chatManager.ChatMessageToOne(Shared.Chat.ChatChannel.Server,
- message,
- wrappedMessage,
- default,
- false,
- connectedClient,
- Color.Red);
+ message = Loc.GetString("ghost-respawn-window-rules-footer");
+ wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", message));
+ return;
}
- else
- {
- var message = Loc.GetString("ghost-respawn-time-left", ("time", (int) (timeUntilRespawn - timePast)));
- var wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", message));
- _chatManager.ChatMessageToOne(Shared.Chat.ChatChannel.Server,
- message,
- wrappedMessage,
- default,
- false,
- connectedClient,
- Color.Red);
- }
- }
- private void ResetDeathTimes(RoundRestartCleanupEvent ev)
- {
- DeathTime.Clear();
+ message = Loc.GetString("ghost-respawn-time-left", ("time", (int) (timeUntilRespawn - timePast)));
+ wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", message));
}
}
diff --git a/Content.Shared/_White/CVars.cs b/Content.Shared/_White/CVars.cs
index cff7de2535..8865b20dcf 100644
--- a/Content.Shared/_White/CVars.cs
+++ b/Content.Shared/_White/CVars.cs
@@ -33,8 +33,8 @@ public static readonly CVarDef
#endregion
#region GhostRespawn
- public static readonly CVarDef GhostRespawnTime =
- CVarDef.Create("ghost.respawn_time", 15f, CVar.SERVERONLY);
+ public static readonly CVarDef GhostRespawnTime =
+ CVarDef.Create("ghost.respawn_time", 15d, CVar.SERVERONLY);
public static readonly CVarDef GhostRespawnMaxPlayers =
CVarDef.Create("ghost.respawn_max_players", 40, CVar.SERVERONLY);
diff --git a/Resources/Locale/en-US/_white/ghost/ghost-respawn.ftl b/Resources/Locale/en-US/_white/ghost/ghost-respawn.ftl
index e45fc16c74..7c5d6f75a8 100644
--- a/Resources/Locale/en-US/_white/ghost/ghost-respawn.ftl
+++ b/Resources/Locale/en-US/_white/ghost/ghost-respawn.ftl
@@ -6,7 +6,6 @@ ghost-respawn-time-left = Before the opportunity to return to the round { $time
ghost-respawn-max-players = The function is not available, there should be fewer players on the server { $players }.
ghost-respawn-window-title = Rules for returning to the round
ghost-respawn-window-rules-footer = By using this feature, you [color=#ff7700]agree[/color] [color=#ff0000]not to transfer[/color] the knowledge of your past character to a new one. For violation of the clause specified here, [color=#ff0000]a ban in the amount of 3 days or more follows[/color].
-ghost-respawn-bug = There is no time of death. The standard value is set.
ghost-respawn-same-character = You cannot enter the round for the same character. Change it in the character settings.
ghost-respawn-log-character-almost-same = Player { $player } { $try ->
diff --git a/Resources/Locale/ru-RU/_white/ghost/ghost-respawn.ftl b/Resources/Locale/ru-RU/_white/ghost/ghost-respawn.ftl
index 402a06f726..eaa118b399 100644
--- a/Resources/Locale/ru-RU/_white/ghost/ghost-respawn.ftl
+++ b/Resources/Locale/ru-RU/_white/ghost/ghost-respawn.ftl
@@ -7,7 +7,6 @@ ghost-respawn-time-left = До возможности вернуться в ра
ghost-respawn-max-players = Функция недоступна, игроков на сервере должно быть меньше { $players }.
ghost-respawn-window-title = Правила возвращения в раунд
ghost-respawn-window-rules-footer = Пользуясь это функцией, вы [color=#ff7700]обязуетесь[/color] [color=#ff0000]не переносить[/color] знания своего прошлого персонажа в нового. За нарушение пункта, указанного здесь, следует [color=#ff0000]бан в размере от 3-ех дней[/color].
-ghost-respawn-bug = Нет времени смерти. Установлено стандартное значение.
ghost-respawn-same-character = Нельзя заходить в раунд за того же персонажа. Поменяйте его в настройках персонажей.
ghost-respawn-log-character-almost-same = Игрок { $player } { $try ->
From 980e442b9d15a478d2e7d5f852fe380d5d5f4c64 Mon Sep 17 00:00:00 2001
From: Spatison <137375981+Spatison@users.noreply.github.com>
Date: Tue, 17 Sep 2024 00:57:03 +0300
Subject: [PATCH 7/7] Update CVars.cs
---
Content.Shared/_White/CVars.cs | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/Content.Shared/_White/CVars.cs b/Content.Shared/_White/CVars.cs
index 0e66d7fb23..48c2f5bd78 100644
--- a/Content.Shared/_White/CVars.cs
+++ b/Content.Shared/_White/CVars.cs
@@ -32,19 +32,19 @@ public static readonly CVarDef
#endregion
-<<<<<<< ghost-respawn
#region GhostRespawn
public static readonly CVarDef GhostRespawnTime =
CVarDef.Create("ghost.respawn_time", 15d, CVar.SERVERONLY);
public static readonly CVarDef GhostRespawnMaxPlayers =
CVarDef.Create("ghost.respawn_max_players", 40, CVar.SERVERONLY);
-=======
+
+ #endregion
+
#region OptionsMisc
public static readonly CVarDef LogInChat =
CVarDef.Create("white.log_in_chat", true, CVar.CLIENT | CVar.ARCHIVE | CVar.REPLICATED);
->>>>>>> master
#endregion
}