Update unit display names when hero text arrives (#4557)

* Update unit display when hero text arrives

Simplify hero name handling to use ClientTextProvider as single source
of truth instead of maintaining a separate cache:
- GetHeroName looks up directly from ClientTextProvider
- Listeners just trigger UpdateAction to refresh UI
- No duplicate caching or manual sync required

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* cleanup

---------

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-23 10:14:31 -08:00
committed by GitHub
co-authored by Claude
parent f938e0dfd9
commit 1ae61b4f15
3 changed files with 27 additions and 25 deletions
@@ -511,8 +511,8 @@ namespace Shardok {
UnitViewWithName unit;
if (!Model.UnitsById.TryGetValue(unitId, out unit)) { return "UNKNOWN"; }
if (unit.AttachedHero?.EagleHeroId is HeroId heroId) {
return Model.GetHeroName(heroId);
if (unit.AttachedHero != null) {
return unit.Name ?? "Hero";
} else if (unit.Battalion.Type == BattalionTypeId.Undead) { // FIXME: hardcoded undead
if (unit.CommandingUnitId is UnitId commandingUnitId) {
return $"[[{HeroNameForUnitId(commandingUnitId)}]]";
@@ -18,24 +18,20 @@ using Hostility = Net.Eagle0.Common.Hostility;
public class ShardokGameModel {
private class HeroNameListener : IClientTextListener {
private readonly HeroId _heroId;
private readonly string _textId;
private readonly ShardokGameModel _model;
public HeroNameListener(HeroId heroId, ShardokGameModel model) {
_heroId = heroId;
public HeroNameListener(string textId, ShardokGameModel model) {
_textId = textId;
_model = model;
}
public void OnTextUpdate(string text, bool completed) {
_model._heroNameCache[_heroId] = text;
_model.UpdateAction?.Invoke();
}
public void OnTextUpdate(string text, bool completed) { _model.UpdateAction?.Invoke(); }
public string TextId() { return _model._heroNameTextIds[_heroId]; }
public string TextId() { return _textId; }
}
private readonly Dictionary<HeroId, string> _heroNameTextIds;
private readonly Dictionary<HeroId, string> _heroNameCache = new();
private readonly List<HeroNameListener> _heroNameListeners = new();
public struct PlayerWithHostility {
@@ -55,9 +51,9 @@ public class ShardokGameModel {
public Dictionary<HeroId, ShardokGameId> HeroImages { get; }
public Dictionary<BattalionId, ShardokGameId> BattalionNames { get; }
public string GetHeroName(HeroId heroId) {
if (_heroNameCache.TryGetValue(heroId, out var name)) { return name; }
return "Hero";
public string GetHeroNameTextId(HeroId heroId) {
_heroNameTextIds.TryGetValue(heroId, out var textId);
return textId;
}
public void CleanupListeners() {
@@ -156,7 +152,7 @@ public class ShardokGameModel {
// Set up listeners for hero names
foreach (var kv in _heroNameTextIds) {
var listener = new HeroNameListener(kv.Key, this);
var listener = new HeroNameListener(kv.Value, this);
_heroNameListeners.Add(listener);
ClientTextProvider.Provider.AddListener(listener);
}
@@ -398,10 +394,10 @@ public class ShardokGameModel {
}
foreach (UnitView changedUnit in gsvDiff.ChangedUnits) {
string name = null;
string heroNameTextId = null;
string headshotPath = null;
if (changedUnit.AttachedHero?.EagleHeroId is HeroId hid) {
name = GetHeroName(hid);
heroNameTextId = GetHeroNameTextId(hid);
HeroImages.TryGetValue(hid, out headshotPath);
}
@@ -412,7 +408,7 @@ public class ShardokGameModel {
UnitsById[changedUnit.UnitId] = new UnitViewWithName(
uv: changedUnit,
name: name,
heroNameTextId: heroNameTextId,
battalionName: battalionName,
headshotPath: headshotPath);
UnitPlayers[changedUnit.UnitId] = changedUnit.PlayerId;
@@ -433,10 +429,10 @@ public class ShardokGameModel {
if (changedReserveUnit.PlayerId != PlayerId) { continue; }
string name = null;
string heroNameTextId = null;
string headshotPath = null;
if (changedReserveUnit.AttachedHero?.EagleHeroId is HeroId hid) {
name = GetHeroName(hid);
heroNameTextId = GetHeroNameTextId(hid);
HeroImages.TryGetValue(hid, out headshotPath);
}
@@ -447,7 +443,7 @@ public class ShardokGameModel {
var uvwn = new UnitViewWithName(
uv: changedReserveUnit,
name: name,
heroNameTextId: heroNameTextId,
battalionName: battalionName,
headshotPath: headshotPath);
@@ -1,4 +1,5 @@
using System;
using eagle;
using Net.Eagle0.Shardok.Api;
using Net.Eagle0.Shardok.Common;
@@ -18,7 +19,7 @@ namespace eagle0 {
Coords newLocation) {
UnitViewWithName newHero = new UnitViewWithName(
uv: unit.Unit.CopyAtLocation(newLocation),
name: unit.Name,
heroNameTextId: unit.HeroNameTextId,
battalionName: unit.BattalionName,
headshotPath: unit.HeadshotPath);
return newHero;
@@ -27,10 +28,15 @@ namespace eagle0 {
public class UnitViewWithName {
public UnitView Unit { get; private set; }
public string Name { get; private set; }
public string HeroNameTextId { get; private set; }
public string BattalionName { get; private set; }
public string HeadshotPath { get; private set; }
public string Name =>
HeroNameTextId != null
? ClientTextProvider.Provider.GetTextEntry(HeroNameTextId)?.Text ?? "Hero"
: null;
public HeroView AttachedHero => Unit.AttachedHero;
public BattalionView Battalion => Unit.Battalion;
public bool Hidden => Unit.Hidden;
@@ -55,11 +61,11 @@ namespace eagle0 {
public UnitViewWithName(
UnitView uv,
string name,
string heroNameTextId,
string battalionName,
string headshotPath) {
Unit = uv;
Name = name;
HeroNameTextId = heroNameTextId;
BattalionName = battalionName;
HeadshotPath = headshotPath;
}