정수형 UI 숫자 표기 검증

This commit is contained in:
2026-07-16 01:50:10 +09:00
parent 0795563185
commit 1180d23728
3 changed files with 65 additions and 0 deletions

18
docs/integer-format.md Normal file
View File

@@ -0,0 +1,18 @@
# Integer Formatting Rules
MapleStory Worlds may serialize numeric properties as strings such as `1.0`.
This is valid numeric data, but it must never be used directly for UI entity
names or paths because `Card1.0` and `DmgPop_1.0` do not exist.
- Use `self:IntStr(value)` for every numeric suffix in a UI path or entity name.
- Use `string.format("%d", math.floor(value or 0))` or `FormatNumber` for an
integer shown in UI text.
- Do not concatenate `tostring(number)` into a `/ui/...` path.
- `tools/deck/gen-slaydeck.mjs` normalizes exact integer strings such as `0.0`
to `0` when regenerating `Global/common.gamelogic`.
Run this check after editing card-controller UI paths:
```powershell
node tools/verify/integer-format.mjs
```

View File

@@ -213,6 +213,21 @@ function writeCodeblocks() {
writeFileSync('RootDesk/MyDesk/SlayDeckController.codeblock', JSON.stringify(combat, null, 2), 'utf8');
}
function normalizeIntegerStrings(value) {
if (Array.isArray(value)) {
for (let index = 0; index < value.length; index++) normalizeIntegerStrings(value[index]);
return;
}
if (value == null || typeof value !== 'object') return;
for (const [key, child] of Object.entries(value)) {
if (typeof child === 'string') {
value[key] = child.replace(/^(-?\d+)\.0+$/, '$1');
} else {
normalizeIntegerStrings(child);
}
}
}
function patchCommon() {
const common = JSON.parse(readFileSync(COMMON_FILE, 'utf8'));
const entity = common.ContentProto.Entities.find((e) => e.path === '/common');
@@ -220,6 +235,7 @@ function patchCommon() {
entity.jsonString['@components'] = [
{ '@type': 'script.SlayDeckController', Enable: true, Energy: 0, MaxEnergy: 3, Turn: 0, TweenEventId: 0 },
];
normalizeIntegerStrings(common);
JSON.parse(JSON.stringify(common));
writeFileSync(COMMON_FILE, JSON.stringify(common, null, 2), 'utf8');
}

View File

@@ -0,0 +1,31 @@
import { readFileSync, readdirSync } from 'node:fs';
import { join } from 'node:path';
const cbDir = 'tools/deck/cb';
const files = readdirSync(cbDir).filter((name) => name.endsWith('.mjs'));
const violations = [];
for (const file of files) {
const source = readFileSync(join(cbDir, file), 'utf8');
const matches = source.match(/["']\/ui\/[^"']*["']\s*\.\.\s*tostring\(/g) || [];
for (const match of matches) violations.push(`${file}: ${match}`);
}
const generator = readFileSync('tools/deck/gen-slaydeck.mjs', 'utf8');
if (!generator.includes('normalizeIntegerStrings(common)')) {
violations.push('gen-slaydeck.mjs: common.gamelogic integer-string normalization is missing');
}
const common = readFileSync('Global/common.gamelogic', 'utf8');
const commonIntegerDecimals = common.match(/(?<![0-9.])-?[0-9]+\.0+(?![0-9])/g) || [];
if (commonIntegerDecimals.length > 0) {
violations.push(`Global/common.gamelogic: integer decimal values ${commonIntegerDecimals.length}`);
}
if (violations.length > 0) {
console.error('UI path integer formatting violations:');
for (const violation of violations) console.error(`- ${violation}`);
process.exit(1);
}
console.log(`integer format: UI path tostring violations 0, common integer decimals 0 (${files.length} modules checked)`);