mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 07:40:43 +00:00
9e9708468c
> **Before opening a PR:** discuss new features on [Discord](https://discord.gg/K9zernJB5z) first, and file bugs or small improvements as [issues](https://github.com/openfrontio/OpenFrontIO/issues/new/choose). You must be assigned to an `approved` issue — unsolicited PRs will be auto-closed. **Add approved & assigned issue number here:** Resolves #4165 ## Description: This PR update the test checking validity of Nation Names to include the new character constraint explained below. It also fixes the 10 Nations that invalid characters (that did not render correctly on the map). **The new character constraint** According to testing, the game map renders correctly all safe Extended-ASCII characters (non colored in www.ascii-code.com = [0x20–0x7E] or [0xA0-0xFF]). Other characters, when present in Nation Names, are rendered correctly in the rest of the game but not on the map, where they are trimmed to the last byte, which is then interpreted as Extended-ASCII and rendered if possible. **How to quickly check my assertion** 1. Change the file resources/maps/world/manifest.json, renaming one of the countries to "a.á.आ!š!慢!". 2. Start a game on the world map without any bots 3. Verify that the nation name is well displayed in its overlay but is shown as "a.á.!a!b!" on the map. (characters before a point are preserved, but characters before an exclamation mark are missing/changed). 4. run `npm run test` and notice that the NationName test fails and lists the three non-valid characters. Explanation: The string is represented in UNICODE-16 as \u0061\u002e\u00e1\u002e\u0906\u0021\u0161\u0021\u6162\u0021. Which, when we keep only the right-most byte of each character gives: 61 2e e1 2e 06 21 61 21 62 21 And, converted in Extended-ASCII gives: a.á.�!a!b! (which matches the showed name if we discard the control character). **The 10 Nations which needed a fix** Utqiaġvik from the Bearing Strait. Ar Rayyān from the Strait of Hormuz. 6 Nations in the Bosphorus Straits. 2 Easter-egg Nations from Luna. The 8 real-world Nations were adapted by simply removing the diacritics (after confirmation from a speaker of arabic and turkish, but sadly none for the Utqiaġvik Nation). The Secret Base from Luna was renamed "T0Þ $e¢®ët Mi|¡tªr¥ ß@§£", all within Extended-ASCII, keeping the same spirit as the original name. However, the Monolith Nation (previously named ▊, without any flag) has changed quite a lot and needs some explanation. **Easter-egg Nation Monolith** The new name is "ΜΟΝΟʟΙȚΗ", which is entirely outside of the valid character zone but in a way that entirely disappears on the map (as the आ character in the example above). This means that on the map, the Nation has no name and only its Monolith-flag. However, in all other places (leaderboard, overlay, alliances, warnings, etc.) the name is displayed correctly. The included test excludes this precise name from its violation list. <img width="1512" height="632" alt="image" src="https://github.com/user-attachments/assets/998693f2-edb4-417c-9054-35dc4819a57d" /> The Monolith Nation without its name but with a Monolith flag. ## Please complete the following: - [x] I have added screenshots for all UI updates - [x] I process any text displayed to the user through translateText() and I've added it to the en.json file - [x] I have added relevant tests to the test directory ## Please put your Discord username so you can be contacted if a bug or regression is found: Katokoda
79 lines
2.8 KiB
TypeScript
79 lines
2.8 KiB
TypeScript
import fs from "fs";
|
||
import { globSync } from "glob";
|
||
|
||
type Nation = {
|
||
name?: string;
|
||
};
|
||
|
||
type Manifest = {
|
||
nations?: Nation[];
|
||
};
|
||
|
||
describe("Map manifests: nation name constraints", () => {
|
||
test("All nations' names must be ≤ 27 printable Extended-ASCII characters", () => {
|
||
const manifestPaths = globSync("resources/maps/**/manifest.json");
|
||
|
||
expect(manifestPaths.length).toBeGreaterThan(0);
|
||
|
||
const violations: string[] = [];
|
||
|
||
for (const manifestPath of manifestPaths) {
|
||
try {
|
||
const raw = fs.readFileSync(manifestPath, "utf8");
|
||
const manifest = JSON.parse(raw) as Manifest;
|
||
|
||
(manifest.nations ?? []).forEach((nation, idx) => {
|
||
const name = nation?.name;
|
||
if (typeof name !== "string") {
|
||
violations.push(
|
||
`${manifestPath} -> nations[${idx}].name is not a string`,
|
||
);
|
||
return;
|
||
}
|
||
if (name.length > 27) {
|
||
violations.push(
|
||
`${manifestPath} -> nations[${idx}].name "${name}" has length ${name.length} (> 27)`,
|
||
);
|
||
return;
|
||
}
|
||
if (name === "ΜΟΝΟʟΙȚΗ") {
|
||
// This exception handles the without-name easter-egg Nation in Luna.
|
||
// The MONOLITH nation have UNICODE characters that DO NOT render in the game-map.
|
||
// Precisely: each bytes of the UNICODE 16-bit code
|
||
// falls **outside** of the Extended-ASCII render-zone: [0x20–0x7E] and [0xA0-0xFF].
|
||
// This magic trick makes its flag stand out, alone, over it's population count.
|
||
// However the name renders correctly in other texts (leaderboard, overlay, alliances, alerts, etc.).
|
||
return;
|
||
}
|
||
// Allow only printable safe-extended-ASCII characters
|
||
// within [0x20-0x7E] or [0xA0-0xFF], as in https://www.ascii-code.com/.
|
||
const excludededCharacters = [...name].filter(
|
||
(c) =>
|
||
c.charCodeAt(0) < 0x20 ||
|
||
(0x7e < c.charCodeAt(0) && c.charCodeAt(0) < 0xa0) ||
|
||
0xff < c.charCodeAt(0),
|
||
);
|
||
if (0 < excludededCharacters.length) {
|
||
violations.push(
|
||
`${manifestPath} -> nations[${idx}].name "${name}" has ${excludededCharacters.length} non valid characters: ${excludededCharacters}`,
|
||
);
|
||
return;
|
||
}
|
||
});
|
||
} catch (err) {
|
||
violations.push(
|
||
`Failed to parse ${manifestPath}: ${(err as Error).message}`,
|
||
);
|
||
}
|
||
}
|
||
|
||
if (violations.length > 0) {
|
||
throw new Error(
|
||
"Nation name violations:\n" +
|
||
violations.join("\n") +
|
||
"\nAll characters must be within non-colored region of the Extended-ASCII table: https://www.ascii-code.com/",
|
||
);
|
||
}
|
||
});
|
||
});
|