0ad/binaries/data/mods/public/gamesettings/attributes/PlayerName.js
Dunedan 93ce94655d
Use @stylistic/brace-style for eslint
Up to now `eslint-plugin-brace-rules` was used to enforce a common brace
style for JavaScript code. This plugin was however updated the last time
over 9 years ago and will be incompatible with ESLint v10, as that
[removes `context.getSourceCode()`][1], the plugin relies on.

To keep the eslint config working with ESLint v10, this replaces
`eslint-plugin-brace-rules` with the [`@stylistic/brace-style`][2] rule
from `@stylistic/eslint-plugin`, a package we already use.

While `@stylistic/brace-style` doesn't offer an option to format braces
in exactly the same way as before, the "allman" style seems to be the
one closest to the existing code.

[1]: https://eslint.org/blog/2025/11/eslint-v10.0.0-alpha.0-released/#removed-deprecated-rule-context-members
[2]: https://eslint.style/rules/brace-style
2026-01-12 21:33:52 +01:00

147 lines
4 KiB
JavaScript

/**
* Stores in-game names for all players.
*
* NB: the regular gamesetup has a particular handling of this setting.
* The names are loaded from the map, but the GUI also show playernames.
* Force these at the start of the match.
*/
GameSettings.prototype.Attributes.PlayerName = class PlayerName extends GameSetting
{
init()
{
// NB: watchers aren't auto-triggered when modifying array elements.
this.values = [];
this.settings.playerCount.watch(() => this.maybeUpdate(), ["nbPlayers"]);
this.settings.map.watch(() => this.onMapChange(), ["map"]);
}
toInitAttributes(attribs)
{
if (!attribs.settings.PlayerData)
attribs.settings.PlayerData = [];
while (attribs.settings.PlayerData.length < this.values.length)
attribs.settings.PlayerData.push({});
for (const i in this.values)
if (this.values[i])
attribs.settings.PlayerData[i].Name = this.values[i];
}
fromInitAttributes(attribs, fromPersistentSettings)
{
if (fromPersistentSettings || !this.getLegacySetting(attribs, "PlayerData"))
return;
const pData = this.getLegacySetting(attribs, "PlayerData");
for (let i = 0; i < this.values.length; ++i)
if (pData[i] && pData[i].Name !== undefined)
{
this.values[i] = pData[i].Name;
this.trigger("values");
}
}
_resize(nb)
{
while (this.values.length > nb)
this.values.pop();
while (this.values.length < nb)
this.values.push(undefined);
}
onMapChange()
{
// Reset.
this._resize(0);
this.maybeUpdate();
}
maybeUpdate()
{
this._resize(this.settings.playerCount.nbPlayers);
this.values.forEach((_, i) => this._set(i));
this.trigger("values");
}
/**
* Pick AI names.
*/
pickRandomItems()
{
const AIPlayerNamesList = [];
let picked = false;
for (const i in this.values)
{
if (!!this.values[i] &&
this.values[i] !== g_Settings.PlayerDefaults[+i + 1].Name)
continue;
const ai = this.settings.playerAI.values[i];
if (!ai)
continue;
const civ = this.settings.playerCiv.values[i];
if (!civ || civ == "random")
continue;
picked = true;
const names = this.settings.civData[civ].AINames;
const remainingNames = names.filter(name => !AIPlayerNamesList.includes(name));
const chosenName = pickRandom(remainingNames.length ? remainingNames : names);
// Avoid translating AI names if the game is networked, so all players see and refer to
// English names instead of names in the language of the host.
const translatedCountLabel = this.settings.isNetworked ? this.CountLabel : translate(this.CountLabel);
const translatedChosenName = this.settings.isNetworked ? chosenName : translate(chosenName);
const duplicateNameCount = AIPlayerNamesList.reduce((count, name) =>
{
if (name == chosenName)
count++;
return count;
}, 0);
AIPlayerNamesList.push(chosenName);
this.values[i] = !duplicateNameCount ? translatedChosenName :
sprintf(translatedCountLabel, {
"playerName": translatedChosenName,
"nameCount": duplicateNameCount + 1
});
}
if (picked)
{
this.trigger("values");
}
return picked;
}
onFinalizeAttributes(attribs, playerAssignments)
{
// Replace client player names with the real players.
for (const guid in playerAssignments)
if (playerAssignments[guid].player !== -1)
attribs.settings.PlayerData[playerAssignments[guid].player -1].Name = playerAssignments[guid].name;
}
_getMapData(i)
{
const data = this.settings.map.data;
if (!data || !data.settings || !data.settings.PlayerData)
return undefined;
if (data.settings.PlayerData.length <= i)
return undefined;
return data.settings.PlayerData[i].Name;
}
_set(playerIndex)
{
this.values[playerIndex] = this._getMapData(playerIndex) || g_Settings && g_Settings.PlayerDefaults[playerIndex + 1].Name || "";
}
};
/** Translation: This is a template (sprintf format specifier) for the name of
* an AI-controlled player and a unique number for each of the players with
* that same name. Example: Perseus (2)
*/
GameSettings.prototype.Attributes.PlayerName.prototype.CountLabel = markForTranslation("%(playerName)s (%(nameCount)i)");