Expose player names to localization.

This commit is contained in:
Matthias Mailänder
2024-07-30 21:23:13 +02:00
committed by Gustas
parent 9a46f3053a
commit 4e5556dccc
39 changed files with 203 additions and 77 deletions

View File

@@ -28,7 +28,7 @@ namespace OpenRA.Mods.Common.Scripting
public string InternalName => Player.InternalName;
[Desc("The player's name.")]
public string Name => Player.PlayerName;
public string Name => Player.ResolvedPlayerName;
[Desc("The player's color.")]
public Color Color => Player.GetColor(Player);

View File

@@ -83,14 +83,14 @@ namespace OpenRA.Mods.Common.Traits
{
if (powerDecision == null)
{
AIUtils.BotDebug("{0} couldn't find powerDecision for {1}", player.PlayerName, sp.Info.OrderName);
AIUtils.BotDebug($"{player.ResolvedPlayerName} couldn't find powerDecision for {sp.Info.OrderName}");
continue;
}
var attackLocation = FindCoarseAttackLocationToSupportPower(sp);
if (attackLocation == null)
{
AIUtils.BotDebug("{0} can't find suitable coarse attack location for support power {1}. Delaying rescan.", player.PlayerName, sp.Info.OrderName);
AIUtils.BotDebug($"{player.ResolvedPlayerName} can't find suitable coarse attack location for support power {sp.Info.OrderName}. Delaying rescan.");
waitingPowers[sp] += powerDecision.GetNextScanTime(world);
continue;
@@ -100,14 +100,14 @@ namespace OpenRA.Mods.Common.Traits
attackLocation = FindFineAttackLocationToSupportPower(sp, (CPos)attackLocation);
if (attackLocation == null)
{
AIUtils.BotDebug("{0} can't find suitable final attack location for support power {1}. Delaying rescan.", player.PlayerName, sp.Info.OrderName);
AIUtils.BotDebug($"{player.ResolvedPlayerName} can't find suitable final attack location for support power {sp.Info.OrderName}. Delaying rescan.");
waitingPowers[sp] += powerDecision.GetNextScanTime(world);
continue;
}
// Valid target found, delay by a few ticks to avoid rescanning before power fires via order
AIUtils.BotDebug("{0} found new target location {1} for support power {2}.", player.PlayerName, attackLocation, sp.Info.OrderName);
AIUtils.BotDebug($"{player.ResolvedPlayerName} found new target location {attackLocation} for support power {sp.Info.OrderName}.");
waitingPowers[sp] += 10;
// Note: SelectDirectionalTarget uses uint.MaxValue in ExtraData to indicate that the player did not pick a direction.
@@ -131,7 +131,7 @@ namespace OpenRA.Mods.Common.Traits
var powerDecision = powerDecisions[readyPower.Info.OrderName];
if (powerDecision == null)
{
AIUtils.BotDebug("{0} couldn't find powerDecision for {1}", player.PlayerName, readyPower.Info.OrderName);
AIUtils.BotDebug($"{player.ResolvedPlayerName} couldn't find powerDecision for {readyPower.Info.OrderName}");
return null;
}
@@ -181,7 +181,7 @@ namespace OpenRA.Mods.Common.Traits
var powerDecision = powerDecisions[readyPower.Info.OrderName];
if (powerDecision == null)
{
AIUtils.BotDebug("{0} couldn't find powerDecision for {1}", player.PlayerName, readyPower.Info.OrderName);
AIUtils.BotDebug($"{player.ResolvedPlayerName} couldn't find powerDecision for {readyPower.Info.OrderName}");
return null;
}

View File

@@ -105,7 +105,7 @@ namespace OpenRA.Mods.Common.Traits
if (info.SuppressNotifications)
return;
TextNotificationsManager.AddSystemLine(PlayerIsDefeated, Translation.Arguments("player", player.PlayerName));
TextNotificationsManager.AddSystemLine(PlayerIsDefeated, Translation.Arguments("player", player.ResolvedPlayerName));
Game.RunAfterDelay(info.NotificationDelay, () =>
{
if (Game.IsCurrentWorld(player.World) && player == player.World.LocalPlayer)
@@ -121,7 +121,7 @@ namespace OpenRA.Mods.Common.Traits
if (info.SuppressNotifications)
return;
TextNotificationsManager.AddSystemLine(PlayerIsVictorious, Translation.Arguments("player", player.PlayerName));
TextNotificationsManager.AddSystemLine(PlayerIsVictorious, Translation.Arguments("player", player.ResolvedPlayerName));
Game.RunAfterDelay(info.NotificationDelay, () =>
{
if (Game.IsCurrentWorld(player.World) && player == player.World.LocalPlayer)

View File

@@ -275,7 +275,7 @@ namespace OpenRA.Mods.Common.Traits
return;
}
var arguments = Translation.Arguments("cheat", order.OrderString, "player", self.Owner.PlayerName, "suffix", debugSuffix);
var arguments = Translation.Arguments("cheat", order.OrderString, "player", self.Owner.ResolvedPlayerName, "suffix", debugSuffix);
TextNotificationsManager.Debug(TranslationProvider.GetString(CheatUsed, arguments));
}

View File

@@ -25,8 +25,9 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Internal id for this bot.")]
public readonly string Type = null;
[TranslationReference]
[Desc("Human-readable name this bot uses.")]
public readonly string Name = "Unnamed Bot";
public readonly string Name = null;
[Desc("Minimum portion of pending orders to issue each tick (e.g. 5 issues at least 1/5th of all pending orders). " +
"Excess orders remain queued for subsequent ticks.")]

View File

@@ -151,7 +151,7 @@ namespace OpenRA.Mods.Common.Traits
if (info.SuppressNotifications)
return;
TextNotificationsManager.AddSystemLine(PlayerIsDefeated, Translation.Arguments("player", player.PlayerName));
TextNotificationsManager.AddSystemLine(PlayerIsDefeated, Translation.Arguments("player", player.ResolvedPlayerName));
Game.RunAfterDelay(info.NotificationDelay, () =>
{
if (Game.IsCurrentWorld(player.World) && player == player.World.LocalPlayer)
@@ -167,7 +167,7 @@ namespace OpenRA.Mods.Common.Traits
if (info.SuppressNotifications)
return;
TextNotificationsManager.AddSystemLine(PlayerIsVictorious, Translation.Arguments("player", player.PlayerName));
TextNotificationsManager.AddSystemLine(PlayerIsVictorious, Translation.Arguments("player", player.ResolvedPlayerName));
Game.RunAfterDelay(info.NotificationDelay, () =>
{
if (Game.IsCurrentWorld(player.World) && player == player.World.LocalPlayer)

View File

@@ -54,7 +54,7 @@ namespace OpenRA.Mods.Common.Traits.Render
font = Game.Renderer.Fonts[info.Font];
this.info = info;
name = self.Owner.PlayerName;
name = self.Owner.ResolvedPlayerName;
if (name.Length > info.MaxLength)
name = name[..info.MaxLength];
}
@@ -73,7 +73,7 @@ namespace OpenRA.Mods.Common.Traits.Render
void INotifyOwnerChanged.OnOwnerChanged(Actor self, Player oldOwner, Player newOwner)
{
name = self.Owner.PlayerName;
name = self.Owner.ResolvedPlayerName;
if (name.Length > Info.MaxLength)
name = name[..Info.MaxLength];
}

View File

@@ -55,7 +55,7 @@ namespace OpenRA.Mods.Common.Traits
var player = new GameInformation.Player
{
ClientIndex = client.Index,
Name = Player.ResolvePlayerName(client, lobbyInfo.Clients, bots),
Name = client.Name,
IsHuman = client.Bot == null,
IsBot = client.Bot != null,
FactionName = resolvedFaction.Name,

View File

@@ -30,7 +30,9 @@ namespace OpenRA.Mods.Common.Traits
if (subjectClient == null)
{
Log.Write("debug", $"Tick {world.WorldTick}: Order sent to {order.Subject.Owner.PlayerName}: resolved ClientIndex `{subjectClientId}` doesn't exist");
Log.Write("debug", $"Tick {world.WorldTick}: " +
$"Order sent to {order.Subject.Owner.ResolvedPlayerName}: " +
$"resolved ClientIndex `{subjectClientId}` doesn't exist");
return false;
}

View File

@@ -81,7 +81,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
TextNotificationsManager.MutedPlayers.Add(c.Index, false);
tabCompletion.Commands = chatTraits.OfType<ChatCommands>().ToArray().SelectMany(x => x.Commands.Keys);
tabCompletion.Names = orderManager.LobbyInfo.Clients.Select(c => c.Name).Distinct().ToList();
tabCompletion.Names = orderManager.LobbyInfo.Clients.Where(c => !c.IsBot).Select(c => c.Name).Distinct().ToList();
if (logicArgs.TryGetValue("Templates", out var templateIds))
{

View File

@@ -65,7 +65,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
public CameraOption(ObserverShroudSelectorLogic logic, Player p)
{
Player = p;
Label = p.PlayerName;
Label = p.ResolvedPlayerName;
Color = p.Color;
Faction = p.Faction.InternalName;
IsSelected = () => p.World.RenderPlayer == p;

View File

@@ -259,7 +259,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
incomeGraph.GetSeries = () =>
players.Select(p => new LineGraphSeries(
p.PlayerName,
p.ResolvedPlayerName,
p.Color,
(p.PlayerActor.TraitOrDefault<PlayerStatistics>() ?? new PlayerStatistics(p.PlayerActor)).IncomeSamples.Select(s => (float)s)));
}
@@ -271,7 +271,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
armyValueGraph.GetSeries = () =>
players.Select(p => new LineGraphSeries(
p.PlayerName,
p.ResolvedPlayerName,
p.Color,
(p.PlayerActor.TraitOrDefault<PlayerStatistics>() ?? new PlayerStatistics(p.PlayerActor)).ArmySamples.Select(s => (float)s)));
}

View File

@@ -112,7 +112,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
if (showOwner)
{
flagFaction = o.Faction.InternalName;
ownerName = o.PlayerName;
ownerName = o.ResolvedPlayerName;
widget.Bounds.Height = doubleHeight;
widget.Bounds.Width = Math.Max(widget.Bounds.Width,
owner.Bounds.X + ownerFont.Measure(ownerName).X + label.Bounds.X);

View File

@@ -853,7 +853,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
while (players.Children.Count > idx)
players.RemoveChild(players.Children[idx]);
tabCompletion.Names = orderManager.LobbyInfo.Clients.Select(c => c.Name).Distinct().ToList();
tabCompletion.Names = orderManager.LobbyInfo.Clients.Where(c => !c.IsBot).Select(c => c.Name).Distinct().ToList();
}
void UpdateDiscordStatus()

View File

@@ -75,7 +75,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
foreach (var b in map.PlayerActorInfo.TraitInfos<IBotInfo>())
{
var botController = orderManager.LobbyInfo.Clients.FirstOrDefault(c => c.IsAdmin);
bots.Add(new SlotDropDownOption(b.Name,
bots.Add(new SlotDropDownOption(TranslationProvider.GetString(b.Name),
$"slot_bot {slot.PlayerReference} {botController.Index} {b.Type}",
() => client != null && client.Bot == b.Type));
}
@@ -422,11 +422,12 @@ namespace OpenRA.Mods.Common.Widgets.Logic
public static void SetupNameWidget(Widget parent, Session.Client c, OrderManager orderManager, WorldRenderer worldRenderer)
{
var name = parent.Get<LabelWidget>("NAME");
name.IsVisible = () => true;
var font = Game.Renderer.Fonts[name.Font];
var label = WidgetUtils.TruncateText(c.Name, name.Bounds.Width, font);
name.GetText = () => label;
var label = parent.Get<LabelWidget>("NAME");
label.IsVisible = () => true;
var font = Game.Renderer.Fonts[label.Font];
var name = c.IsBot ? TranslationProvider.GetString(c.Name) : c.Name;
var text = WidgetUtils.TruncateText(name, label.Bounds.Width, font);
label.GetText = () => text;
SetupProfileWidget(parent, c, orderManager, worldRenderer);
}
@@ -444,7 +445,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic
var closed = TranslationProvider.GetString(Closed);
var open = TranslationProvider.GetString(Open);
slot.GetText = () => truncated.Update(c != null ? c.Name : s.Closed ? closed : open);
slot.GetText = () => truncated.Update(c != null ?
c.IsBot ? TranslationProvider.GetString(c.Name) : c.Name
: s.Closed ? closed : open);
slot.OnMouseDown = _ => ShowSlotDropDown(slot, s, c, orderManager, map, modData);
// Ensure Name selector (if present) is hidden

View File

@@ -407,7 +407,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic
var ddb = panel.GetOrNull<DropDownButtonWidget>("FLT_PLAYER_DROPDOWNBUTTON");
if (ddb != null)
{
var options = replays.SelectMany(r => r.GameInfo.Players.Select(p => p.Name)).Distinct(StringComparer.OrdinalIgnoreCase).ToList();
var options = replays.SelectMany(r => r.GameInfo.Players.Select(p => r.GameInfo.ResolvedPlayerName(p)))
.Distinct(StringComparer.OrdinalIgnoreCase).ToList();
options.Sort(StringComparer.OrdinalIgnoreCase);
options.Insert(0, null); // no filter
@@ -666,7 +668,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
if (!string.IsNullOrEmpty(filter.PlayerName))
{
var player = replay.GameInfo.Players.FirstOrDefault(
p => string.Equals(filter.PlayerName, p.Name, StringComparison.CurrentCultureIgnoreCase));
p => string.Equals(filter.PlayerName, replay.GameInfo.ResolvedPlayerName(p), StringComparison.CurrentCultureIgnoreCase));
if (player == null)
return false;
@@ -751,7 +753,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
var label = item.Get<LabelWidget>("LABEL");
var font = Game.Renderer.Fonts[label.Font];
var name = WidgetUtils.TruncateText(o.Name, label.Bounds.Width, font);
var name = WidgetUtils.TruncateText(replay.GameInfo.ResolvedPlayerName(o), label.Bounds.Width, font);
label.GetText = () => name;
label.GetColor = () => color;

View File

@@ -30,7 +30,7 @@ namespace OpenRA.Mods.Common.Widgets
public SpawnOccupant(Session.Client client)
{
Color = client.Color;
PlayerName = client.Name;
PlayerName = client.IsBot ? TranslationProvider.GetString(client.Name) : client.Name;;
Team = client.Team;
Faction = client.Faction;
SpawnPoint = client.SpawnPoint;
@@ -39,7 +39,7 @@ namespace OpenRA.Mods.Common.Widgets
public SpawnOccupant(GameInformation.Player player)
{
Color = player.Color;
PlayerName = player.Name;
PlayerName = player.IsBot ? TranslationProvider.GetString(player.Name) : player.Name;
Team = player.Team;
Faction = player.FactionId;
SpawnPoint = player.SpawnPoint;
@@ -48,7 +48,7 @@ namespace OpenRA.Mods.Common.Widgets
public SpawnOccupant(GameClient player, bool suppressFaction)
{
Color = player.Color;
PlayerName = player.Name;
PlayerName = player.IsBot ? TranslationProvider.GetString(player.Name) : player.Name;
Team = player.Team;
Faction = !suppressFaction ? player.Faction : null;
SpawnPoint = player.SpawnPoint;

View File

@@ -59,7 +59,7 @@ namespace OpenRA.Mods.Common.Widgets
{
var self = p.Instances[0].Self;
var time = WidgetUtils.FormatTime(p.RemainingTicks, false, self.World.Timestep);
var text = TranslationProvider.GetString(Format, Translation.Arguments("player", self.Owner.PlayerName, "support-power", p.Name, "time", time));
var text = TranslationProvider.GetString(Format, Translation.Arguments("player", self.Owner.ResolvedPlayerName, "support-power", p.Name, "time", time));
var color = !p.Ready || Game.LocalTick % 50 < 25 ? self.OwnerColor() : Color.White;

View File

@@ -20,6 +20,15 @@ namespace OpenRA.Mods.Common.Widgets
{
public static class WidgetUtils
{
[TranslationReference]
const string Gone = "label-client-state-disconnected";
[TranslationReference]
const string Won = "label-win-state-won";
[TranslationReference]
const string Lost = "label-win-state-lost";
public static string GetStatefulImageName(
string baseName, bool disabled = false, bool pressed = false, bool hover = false, bool focused = false)
{
@@ -324,19 +333,29 @@ namespace OpenRA.Mods.Common.Widgets
{
var client = p.World.LobbyInfo.ClientWithIndex(p.ClientIndex);
var nameFont = Game.Renderer.Fonts[label.Font];
var name = new CachedTransform<(string Name, WinState WinState, Session.ClientState ClientState), string>(c =>
var name = new CachedTransform<(WinState WinState, Session.ClientState ClientState), string>(c =>
{
var suffix = c.WinState == WinState.Undefined ? "" : " (" + c.WinState + ")";
if (c.ClientState == Session.ClientState.Disconnected)
suffix = " (Gone)";
var text = p.ResolvedPlayerName;
return TruncateText(c.Name, label.Bounds.Width - nameFont.Measure(suffix).X, nameFont) + suffix;
var suffix = "";
if (c.WinState == WinState.Won)
suffix = $" ({TranslationProvider.GetString(Won)})";
else if (c.WinState == WinState.Lost)
suffix = $" ({TranslationProvider.GetString(Lost)})";
if (client.State == Session.ClientState.Disconnected)
suffix = $" ({TranslationProvider.GetString(Gone)})";
text += suffix;
var size = nameFont.Measure(text) - nameFont.Measure(p.ResolvedPlayerName);
return TruncateText(text, label.Bounds.Width - size.X, nameFont);
});
label.GetText = () =>
{
var clientState = client != null ? client.State : Session.ClientState.Ready;
return name.Update((p.PlayerName, p.WinState, clientState));
return name.Update((p.WinState, clientState));
};
}