# @combos-fun/plugin-renderer-3d-text

@combos-fun/plugin-renderer-3d-text — part of the Combos Fun engine monorepo.

Keywords: `3d`, `text`, `label`, `troika`, `font`.

## Documentation

- Per-package agent / developer notes: [`agent-skill.md`](./agent-skill.md)
- Machine-readable manifest: [`combos-plugin.json`](./combos-plugin.json)
  (validated against `schemas/combos-plugin.schema.json` in the repo
  root)
- Entry skill (single source of truth for AI agents working with this
  monorepo): `skills/combos-engine-development/SKILL.md`

When consumed from npm, the manifest and agent notes are exposed as
stable subpaths:

```ts
import manifest from '@combos-fun/plugin-renderer-3d-text/plugin-manifest';
// or fetch the markdown directly:
// require.resolve('@combos-fun/plugin-renderer-3d-text/agent-skill')
```

## Host-driven i18n

Same host contract as `@combos-fun/plugin-renderer-text`. Configure the source
locale on the 3D text system. Locale names use BCP 47 tags.

```ts
const textSystem = new Text3DSystem({
  sourceLocale: 'zh-CN',
  sourceTexts: [
    '{player} 获得了 {score} 分',
    '开始游戏',
    '下一屏文案',
  ],
});
```

```ts
new Text3D({
  text: '{player} 获得了 {score} 分',
  replacements: {
    player: 'Alice',
    score: 100,
  },
});
```

The host injects `window.combos` into the game HTML head. The first
`requestI18n` runs in `beforeReady` and holds `combos-game:ready` / `start`
until the host replies. Labels stay empty until that reply so source copy does
not paint first. Put every later-screen template in `sourceTexts` so
those screens reuse the startup catalog instead of flashing source text.
The system keeps one growing session catalog of source templates and
translations; later `requestI18n` calls only send templates still missing
from that catalog.
If the host returns `needed: true` but a template is missing from
`translations`, the system sends only the still-untranslated texts and waits
for one more `requestI18n` before showing that label. Returning to copy that is already in
`translations` does not call `requestI18n` again. Translation is applied only when
the result is `needed: true`. Without the injected SDK, the game stays on
the source text.

## License

Internal workspace package, part of the Combos Fun engine monorepo.
