@the-inclusionist/engine 8.0.0-rc.1 → 8.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/public/vendor/fonts/playwrite-ar.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-br.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-ca.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-cl.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-co.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-mx.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-us-modern.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-us-trad.woff2 +0 -0
- package/app/public/vendor/fonts.css +21 -0
- package/dist-pkg/boot/create-game.d.ts +33 -4
- package/dist-pkg/boot/create-game.js +72 -11
- package/dist-pkg/core/contract.d.ts +60 -0
- package/dist-pkg/core/contract.js +42 -0
- package/dist-pkg/i18n/en.js +11 -0
- package/dist-pkg/i18n/es.js +11 -0
- package/dist-pkg/i18n/pt.js +14 -0
- package/dist-pkg/input/default-bindings.js +20 -12
- package/dist-pkg/input/gamepad.d.ts +15 -1
- package/dist-pkg/input/gamepad.js +30 -9
- package/dist-pkg/input/keyboard.d.ts +32 -0
- package/dist-pkg/input/keyboard.js +46 -6
- package/dist-pkg/input/keydown.d.ts +13 -0
- package/dist-pkg/input/keydown.js +9 -0
- package/dist-pkg/input/latch-edge.d.ts +28 -0
- package/dist-pkg/input/latch-edge.js +45 -0
- package/dist-pkg/input/latch-sync.d.ts +47 -0
- package/dist-pkg/input/latch-sync.js +43 -0
- package/dist-pkg/input/pad-defaults.d.ts +22 -0
- package/dist-pkg/input/pad-defaults.js +34 -0
- package/dist-pkg/input/touch-bindings.d.ts +10 -0
- package/dist-pkg/input/touch-bindings.js +6 -0
- package/dist-pkg/platform/pesados-catalogo.d.ts +14 -0
- package/dist-pkg/platform/pesados-catalogo.js +177 -0
- package/dist-pkg/platform/pesados.d.ts +31 -0
- package/dist-pkg/platform/pesados.js +75 -0
- package/dist-pkg/platform/voice-plan.d.ts +20 -1
- package/dist-pkg/platform/voice-plan.js +20 -1
- package/dist-pkg/platform/vozes-prontas.d.ts +28 -0
- package/dist-pkg/platform/vozes-prontas.js +61 -0
- package/dist-pkg/ui/fonts.d.ts +24 -0
- package/dist-pkg/ui/fonts.js +66 -1
- package/dist-pkg/ui/pause-icons.d.ts +36 -2
- package/dist-pkg/ui/pause-icons.js +9 -1
- package/dist-pkg/ui/settings-motor.d.ts +21 -1
- package/dist-pkg/ui/settings-motor.js +22 -4
- package/dist-pkg/ui/settings-typo.d.ts +18 -4
- package/dist-pkg/ui/settings-typo.js +16 -11
- package/docs/CREDITS.md +15 -12
- package/docs/LICENSES.md +170 -144
- package/package.json +2 -1
|
@@ -10,6 +10,7 @@ import { t } from '../core/i18n.js';
|
|
|
10
10
|
import { EDGE_BY_ACTION, edgeAllowed } from './edges.js';
|
|
11
11
|
import { migrarMapaDeControle } from './vocabulary-migration.js';
|
|
12
12
|
import { GAMEPAD_STANDARD } from './default-bindings.js';
|
|
13
|
+
import { tabelaDoPad } from './pad-defaults.js';
|
|
13
14
|
import { padCur, padPrevAct, padPrevStart, PAD_DEAD } from './state.js';
|
|
14
15
|
// ⚠️ O `oneButton` ENTRA POR IMPORT, e não pelo `ctx` — ao contrário de `input/keydown`, que o recebe por
|
|
15
16
|
// getter. A diferença não é de gosto: o `keydown` foi extraído quando o `oneButton` era um `let` do
|
|
@@ -72,7 +73,7 @@ export function bindActive(gp, bd) {
|
|
|
72
73
|
/** Ações do frame para este gamepad. `custom` = mapa salvo pelo wizard para este `gp.id` (null/`_skip` = usa o
|
|
73
74
|
* mapa PADRÃO da Gamepad API "standard": 0=pulo · 1=especial · 2/5/7=correr · 3=troca · 9=START). Direções
|
|
74
75
|
* custom caem de volta em stdDirs quando o binding do usuário não está ativo (D-pad/stick continuam vivos). */
|
|
75
|
-
export function padActions(gp, custom) {
|
|
76
|
+
export function padActions(gp, custom, tabela = GAMEPAD_STANDARD) {
|
|
76
77
|
if (custom && !custom._skip) {
|
|
77
78
|
const A = (k) => bindActive(gp, bindingAt(custom, k));
|
|
78
79
|
const sd = stdDirs(gp);
|
|
@@ -91,7 +92,12 @@ export function padActions(gp, custom) {
|
|
|
91
92
|
// correr, enquanto a tabela declara R1 como `rightShoulder` e R2 como `rightTrigger`. O ADR-0086 registrou
|
|
92
93
|
// esta mudança como o asterisco do seu «zero movimento»: nenhum VERBO muda de botão, mas `run` perde dois
|
|
93
94
|
// dos seus três. Quem usava R1 para correr sente — e é o preço de os quatro ombros existirem.
|
|
94
|
-
|
|
95
|
+
// 📌 A TABELA CHEGA POR PARÂMETRO desde o ADR-0115: é a fábrica da engine COM o padrão deste jogo por cima,
|
|
96
|
+
// resolvida em `input/pad-defaults`. O padrão da assinatura é o da engine, então quem chamava com dois
|
|
97
|
+
// argumentos continua a ler exactamente o que lia.
|
|
98
|
+
// ⚠️ E ela só decide neste ramo, que é o certo: o ramo de cima é o mapa que a CRIANÇA gravou no assistente,
|
|
99
|
+
// e o padrão de um jogo não se sobrepõe a uma escolha dela.
|
|
100
|
+
const B = tabela;
|
|
95
101
|
const at = (a) => { const i = B[a]; return typeof i === 'number' ? b(i) : false; };
|
|
96
102
|
return {
|
|
97
103
|
left: sd.left, right: sd.right, up: sd.up, down: sd.down,
|
|
@@ -220,7 +226,7 @@ export function initGamepad(ctx) {
|
|
|
220
226
|
}
|
|
221
227
|
return _padMaps.get(id) ?? null;
|
|
222
228
|
}
|
|
223
|
-
function actionsFor(gp) { return padActions(gp, padMapFor(gp.id)); }
|
|
229
|
+
function actionsFor(gp, tabela) { return padActions(gp, padMapFor(gp.id), tabela); }
|
|
224
230
|
// ----- wizard: anúncio + demo animada (DOM-facing, thin) -----
|
|
225
231
|
// ⚠️ O PARÂMETRO CHAMAVA-SE `t`, E ERA ELE QUE FECHAVA A PORTA. Dentro desta função o `t` do
|
|
226
232
|
// `core/i18n` estava sombreado, então traduzir uma frase aqui era impossível sem primeiro reparar no
|
|
@@ -470,9 +476,17 @@ export function initGamepad(ctx) {
|
|
|
470
476
|
return;
|
|
471
477
|
}
|
|
472
478
|
const prev = padPrevAct[gi] || {};
|
|
473
|
-
// ⚠️
|
|
479
|
+
// ⚠️ O ASSENTO SUBIU PARA AQUI, e a razão é o ADR-0115: a tabela de botões deste jogo é declarada POR
|
|
480
|
+
// ASSENTO, e ela é lida dentro do `actionsFor`. Enquanto o `owner` só se resolvia lá em baixo, por ramo,
|
|
481
|
+
// a leitura acontecia antes de se saber de quem era o controle — e um padrão por assento chegava tarde.
|
|
482
|
+
// 📌 Os ramos abaixo passaram a usar esta constante em vez de recalcularem a mesma linha três vezes.
|
|
483
|
+
const players = ctx.getPlayers();
|
|
484
|
+
const owner = players.findIndex((p) => p.pad === gi);
|
|
485
|
+
// ⚠️ E O CONTROLE AINDA NÃO ATRIBUÍDO (`owner < 0`) LÊ O ASSENTO 0, e não «nenhum»: ele está a produzir
|
|
486
|
+
// arestas na tela do título, e um mapa vazio ali deixaria a criança sem como escolher o próprio jogo.
|
|
487
|
+
// A EMPATIA MOTORA APLICADA AO CONTROLE (issue #120). Sem esta linha, uma criança com o modo de
|
|
474
488
|
// um botão ligado e um pad na mão NÃO ESTAVA no modo — e nada em lado nenhum o dizia.
|
|
475
|
-
const cur = umBotaoPorVez(prev, actionsFor(gp), estadoDoJogo.oneButton);
|
|
489
|
+
const cur = umBotaoPorVez(prev, actionsFor(gp, tabelaDoPad(ctx.getNumPlayers(), owner < 0 ? 0 : owner)), estadoDoJogo.oneButton);
|
|
476
490
|
if (ctx.isTouchMode() && (cur.left || cur.right || cur.up || cur.down || cur.action2 || cur.action1 || cur.action4 || cur.action3 || cur._start)) {
|
|
477
491
|
ctx.hideTouchControls(); // botão físico usado -> some o gamepad virtual (mesma regra do teclado)
|
|
478
492
|
}
|
|
@@ -495,11 +509,9 @@ export function initGamepad(ctx) {
|
|
|
495
509
|
// de propósito: numa cena que este módulo não conheça (um mapa, uma tela de resultados), o controle
|
|
496
510
|
// deve navegar como no título — que é o comportamento seguro — em vez de não fazer nada.
|
|
497
511
|
const rodando = ctx.mundoRodando(), pausado = ctx.menuDePausa();
|
|
498
|
-
const players = ctx.getPlayers();
|
|
499
512
|
if (!rodando && !pausado) {
|
|
500
513
|
const k = { yes: edge('action2') || startEdge, no: edge('action3'), up: edge('up'), down: edge('down'), left: edge('left'), right: edge('right') };
|
|
501
514
|
const any = k.yes || k.no || k.up || k.down || k.left || k.right;
|
|
502
|
-
const owner = players.findIndex((p) => p.pad === gi);
|
|
503
515
|
if (ctx.getNumPlayers() > 1 && owner > 0) {
|
|
504
516
|
if (any)
|
|
505
517
|
ctx.srSay(t('sr.title.waitP1'));
|
|
@@ -510,7 +522,6 @@ export function initGamepad(ctx) {
|
|
|
510
522
|
continue;
|
|
511
523
|
}
|
|
512
524
|
if (pausado) {
|
|
513
|
-
const owner = players.findIndex((p) => p.pad === gi);
|
|
514
525
|
const pi = owner < 0 ? 0 : owner;
|
|
515
526
|
if (pauseEdge) {
|
|
516
527
|
ctx.retomar();
|
|
@@ -530,7 +541,6 @@ export function initGamepad(ctx) {
|
|
|
530
541
|
continue;
|
|
531
542
|
}
|
|
532
543
|
if (rodando) {
|
|
533
|
-
const owner = players.findIndex((p) => p.pad === gi);
|
|
534
544
|
// ===================== O MODO `accessibility` (ADR-0044, item 7) =====================
|
|
535
545
|
// Com o jogo ANDANDO, o direcional deste jogador dirige a BARRA RÁPIDA e não o personagem. Vem antes
|
|
536
546
|
// de tudo o que é de jogo, porque enquanto o modo está ligado nada mais deste controle é de jogo.
|
|
@@ -585,10 +595,21 @@ export function initGamepad(ctx) {
|
|
|
585
595
|
}
|
|
586
596
|
// A tabela e a guarda do Fácil vêm de input/edges.ts, as MESMAS que keydown e touch usam. Antes eram
|
|
587
597
|
// seis `if` à mão aqui, seis lá e seis no toque — e o do toque tinha esquecido o `!p.easy`.
|
|
598
|
+
let algumaAresta = false;
|
|
588
599
|
for (const [act, flag] of EDGE_BY_ACTION) {
|
|
600
|
+
if (edge(act))
|
|
601
|
+
algumaAresta = true;
|
|
589
602
|
if (edgeAllowed(act, p.easy) && edge(act))
|
|
590
603
|
p[flag] = true;
|
|
591
604
|
}
|
|
605
|
+
// 📌 A ARESTA DO CONTROLE, e ela conta MESMO QUANDO O FÁCIL A FILTRA (ADR-0113 cláusula 4): a
|
|
606
|
+
// criança carregou no botão — que a regra do Modo Fácil não levante a bandeira do jogo não muda
|
|
607
|
+
// o facto de o aparelho em uso ser este. Ler a mesma condição do `p[flag]` faria uma criança em
|
|
608
|
+
// Modo Fácil ficar com a alternância do teclado enquanto joga no controle.
|
|
609
|
+
// ⚠️ E É AQUI, no ramo de JOGO, e não nos de menu: `naBarraDe`, o título e a pausa são navegação, e
|
|
610
|
+
// a pergunta que isto alimenta — que alternância vale AGORA — é sobre jogar.
|
|
611
|
+
if (algumaAresta)
|
|
612
|
+
ctx.arestaDoJogador(owner, 'gamepad');
|
|
592
613
|
}
|
|
593
614
|
}
|
|
594
615
|
}
|
|
@@ -31,6 +31,32 @@ export declare const KB_SCHEMES4: KeyScheme[];
|
|
|
31
31
|
* voltar a existir, em vez de a apanhar depois de acontecer.
|
|
32
32
|
*/
|
|
33
33
|
export declare const KB_DEFAULTS: KBDefaults;
|
|
34
|
+
/**
|
|
35
|
+
* O PADRÃO QUE O JOGO QUER, por número de jogadores e por assento (ADR-0115). Parcial: o que ele não disser
|
|
36
|
+
* fica como a fábrica da engine o deixou.
|
|
37
|
+
*/
|
|
38
|
+
export type MapeamentoDoTeclado = (jogadores: number, assento: number) => Partial<KeyScheme> | null;
|
|
39
|
+
/**
|
|
40
|
+
* REGISTA O PADRÃO DO JOGO. Chamado uma vez pelo arranque (`boot/create-game`), a partir da declaração.
|
|
41
|
+
*
|
|
42
|
+
* 🔴 REGISTO E NÃO PARÂMETRO, e a razão é um defeito medido em vez de uma preferência. Há DOIS sítios que
|
|
43
|
+
* materializam padrões — `loadKB` e `resetKB` — e o segundo é chamado pelo painel de controles, que não tem a
|
|
44
|
+
* declaração do jogo à mão. Um parâmetro que o painel não passasse faria «restaurar padrões» devolver o mapa
|
|
45
|
+
* da ENGINE por cima do mapa do JOGO: a criança carrega no botão esperando voltar ao que o jogo lhe deu, e
|
|
46
|
+
* volta para outra coisa — num jogo cujo autor escolheu o layout por uma razão de acessibilidade, ela perde
|
|
47
|
+
* essa razão e nada o diz.
|
|
48
|
+
*
|
|
49
|
+
* 📌 É a mesma forma que o `kb` deste ficheiro já tem, e pela mesma justificação: o dono é evidente, e as
|
|
50
|
+
* funções que o gerem vivem todas aqui.
|
|
51
|
+
*/
|
|
52
|
+
export declare function registrarMapeamentoDoTeclado(f: MapeamentoDoTeclado | null): void;
|
|
53
|
+
/**
|
|
54
|
+
* A FÁBRICA COM O PADRÃO DO JOGO POR CIMA — a **única** resolução, usada pelo `loadKB` E pelo `resetKB`.
|
|
55
|
+
*
|
|
56
|
+
* ⚠️ Uma função só, e é o ponto inteiro: enquanto eram duas cópias do `JSON.parse(JSON.stringify(...))`, a do
|
|
57
|
+
* `resetKB` não conhecia o jogo e a diferença só aparecia quando uma criança carregava em «restaurar».
|
|
58
|
+
*/
|
|
59
|
+
export declare function fabricaComOJogo(): KBDefaults;
|
|
34
60
|
export declare function loadKB(): KBDefaults;
|
|
35
61
|
export declare function saveKB(kb: KBDefaults): void;
|
|
36
62
|
/**
|
|
@@ -52,4 +78,10 @@ export declare function initKB(): KBDefaults;
|
|
|
52
78
|
/** Troca o mapa inteiro. Só o "restaurar padrões" do painel de controles precisa disto — remapear uma tecla
|
|
53
79
|
* MUTA o objeto, e reatribuir por engano faria as referências vivas apontarem para o mapa antigo. */
|
|
54
80
|
export declare function setKB(next: KBDefaults): void;
|
|
81
|
+
/**
|
|
82
|
+
* «RESTAURAR PADRÕES» — e o padrão para onde ela volta é o DO JOGO, não o da engine (ADR-0115).
|
|
83
|
+
*
|
|
84
|
+
* 🔴 Esta linha era `JSON.parse(JSON.stringify(KB_DEFAULTS))`, e com o campo do jogo a existir isso passaria
|
|
85
|
+
* a apagar em silêncio o mapeamento que o jogo escolheu. A criança espera voltar ao que o jogo lhe deu.
|
|
86
|
+
*/
|
|
55
87
|
export declare function resetKB(): KBDefaults;
|
|
@@ -57,13 +57,47 @@ export const KB_DEFAULTS = {
|
|
|
57
57
|
// A FORMA vem de `vocabulary-migration`, que é quem a traduz — declarar aqui outra vez seria a
|
|
58
58
|
// cópia que o `core/entity` passou o mês a eliminar.
|
|
59
59
|
import { migrarSalvo } from './vocabulary-migration.js';
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
60
|
+
let mapeamentoDoJogo = null;
|
|
61
|
+
/**
|
|
62
|
+
* REGISTA O PADRÃO DO JOGO. Chamado uma vez pelo arranque (`boot/create-game`), a partir da declaração.
|
|
63
|
+
*
|
|
64
|
+
* 🔴 REGISTO E NÃO PARÂMETRO, e a razão é um defeito medido em vez de uma preferência. Há DOIS sítios que
|
|
65
|
+
* materializam padrões — `loadKB` e `resetKB` — e o segundo é chamado pelo painel de controles, que não tem a
|
|
66
|
+
* declaração do jogo à mão. Um parâmetro que o painel não passasse faria «restaurar padrões» devolver o mapa
|
|
67
|
+
* da ENGINE por cima do mapa do JOGO: a criança carrega no botão esperando voltar ao que o jogo lhe deu, e
|
|
68
|
+
* volta para outra coisa — num jogo cujo autor escolheu o layout por uma razão de acessibilidade, ela perde
|
|
69
|
+
* essa razão e nada o diz.
|
|
70
|
+
*
|
|
71
|
+
* 📌 É a mesma forma que o `kb` deste ficheiro já tem, e pela mesma justificação: o dono é evidente, e as
|
|
72
|
+
* funções que o gerem vivem todas aqui.
|
|
73
|
+
*/
|
|
74
|
+
export function registrarMapeamentoDoTeclado(f) { mapeamentoDoJogo = f; }
|
|
75
|
+
/**
|
|
76
|
+
* A FÁBRICA COM O PADRÃO DO JOGO POR CIMA — a **única** resolução, usada pelo `loadKB` E pelo `resetKB`.
|
|
77
|
+
*
|
|
78
|
+
* ⚠️ Uma função só, e é o ponto inteiro: enquanto eram duas cópias do `JSON.parse(JSON.stringify(...))`, a do
|
|
79
|
+
* `resetKB` não conhecia o jogo e a diferença só aparecia quando uma criança carregava em «restaurar».
|
|
80
|
+
*/
|
|
81
|
+
export function fabricaComOJogo() {
|
|
82
|
+
const d = JSON.parse(JSON.stringify(KB_DEFAULTS));
|
|
83
|
+
if (!mapeamentoDoJogo)
|
|
84
|
+
return d;
|
|
85
|
+
const aplicar = (alvo, jogadores, assento) => {
|
|
86
|
+
const parcial = mapeamentoDoJogo(jogadores, assento);
|
|
87
|
+
if (parcial)
|
|
88
|
+
Object.assign(alvo, parcial);
|
|
89
|
+
};
|
|
90
|
+
aplicar(d.solo, 1, 0);
|
|
91
|
+
d.p2.forEach((esq, i) => aplicar(esq, 2, i));
|
|
92
|
+
d.p3.forEach((esq, i) => aplicar(esq, 3, i));
|
|
93
|
+
d.p4.forEach((esq, i) => aplicar(esq, 4, i));
|
|
94
|
+
return d;
|
|
95
|
+
}
|
|
64
96
|
// carrega os esquemas salvos SOBRE os defaults (com migração do dado antigo p34 → p3+p4)
|
|
65
97
|
export function loadKB() {
|
|
66
|
-
|
|
98
|
+
// ⚠️ A PRECEDÊNCIA É ESTA E ESTÁ ESCRITA UMA VEZ: fábrica da engine → padrão do JOGO → remapeamento da
|
|
99
|
+
// CRIANÇA. O que a criança gravou vem sempre por último, porque é a única das três que ela escolheu.
|
|
100
|
+
const d = fabricaComOJogo();
|
|
67
101
|
// ⚠️ O DADO SALVO ATRAVESSA O TRADUTOR ANTES DE TOCAR NOS PADRÕES. Sem esta linha, um esquema gravado com
|
|
68
102
|
// as chaves antigas (`run`, `jump`, `swap`, `especial`) seria fundido sobre defaults que já usam
|
|
69
103
|
// `action1`..`action4`: o objeto ficaria com AS DUAS famílias de chaves, os transportes leriam só as novas,
|
|
@@ -107,4 +141,10 @@ export function initKB() { kb = loadKB(); return kb; }
|
|
|
107
141
|
/** Troca o mapa inteiro. Só o "restaurar padrões" do painel de controles precisa disto — remapear uma tecla
|
|
108
142
|
* MUTA o objeto, e reatribuir por engano faria as referências vivas apontarem para o mapa antigo. */
|
|
109
143
|
export function setKB(next) { kb = next; }
|
|
110
|
-
|
|
144
|
+
/**
|
|
145
|
+
* «RESTAURAR PADRÕES» — e o padrão para onde ela volta é o DO JOGO, não o da engine (ADR-0115).
|
|
146
|
+
*
|
|
147
|
+
* 🔴 Esta linha era `JSON.parse(JSON.stringify(KB_DEFAULTS))`, e com o campo do jogo a existir isso passaria
|
|
148
|
+
* a apagar em silêncio o mapeamento que o jogo escolheu. A criança espera voltar ao que o jogo lhe deu.
|
|
149
|
+
*/
|
|
150
|
+
export function resetKB() { store.remove(CKEY); return fabricaComOJogo(); }
|
|
@@ -245,6 +245,19 @@ export interface KeydownCtx {
|
|
|
245
245
|
* que ela existe, e é justamente ele quem produz os eventos que caem aqui.
|
|
246
246
|
*/
|
|
247
247
|
marcarTeclaSemOrigem: (code: string) => void;
|
|
248
|
+
/**
|
|
249
|
+
* ESTA ARESTA É DESTE JOGADOR, E VEIO DAQUI (ADR-0113 cláusula 4, issue #127) — `input/state.arestaDoJogador`.
|
|
250
|
+
*
|
|
251
|
+
* 🔴 CAMPO OBRIGATÓRIO, e a medição é a razão: em 2026-09-09 o autómato do ADR-0109 tinha ZERO alimentadores
|
|
252
|
+
* em produção, logo `entradaDe(i).emUso` respondia `teclado` a toda a gente — para sempre, e sem erro
|
|
253
|
+
* nenhum. Com isso, a recusa da cláusula 3 nunca dispara: a criança que joga por webcam consegue desligar a
|
|
254
|
+
* alternância de que a entrada dela depende, e nada o diz.
|
|
255
|
+
*
|
|
256
|
+
* ⚠️ E É AQUI QUE ELE VALE, e não no teclado que já é o padrão: o evento sintético que a webcam despacha
|
|
257
|
+
* chega carimbado (`input/origem-sintetica`), então é por esta linha que `olhos`/`rosto`/`gestos`/`fala`
|
|
258
|
+
* passam a ser o transporte em uso. Uma tecla premida a sério devolve o teclado, que é a regra 3 do ADR-0109.
|
|
259
|
+
*/
|
|
260
|
+
arestaDoJogador: (jogador: number, origem: Transporte) => void;
|
|
248
261
|
soltarTecla: (code: string) => void;
|
|
249
262
|
/** `let oneButton` do game.js (empatia motora) → getter. */
|
|
250
263
|
isOneButton: () => boolean;
|
|
@@ -368,6 +368,15 @@ export function initKeydown(ctx) {
|
|
|
368
368
|
ctx.marcarTecla(code, origem);
|
|
369
369
|
else
|
|
370
370
|
ctx.marcarTeclaSemOrigem(code);
|
|
371
|
+
// 📌 A ARESTA ALIMENTA O AUTÓMATO NO MESMO PONTO E SOB A MESMA CONDIÇÃO em que a origem é gravada na
|
|
372
|
+
// tecla — origem desconhecida não é aresta de aparelho nenhum, e inventar-lhe `teclado` faria uma
|
|
373
|
+
// tecla do toque desligar a alternância de quem joga por olhar, sem erro e no meio da partida.
|
|
374
|
+
// ⚠️ Tecla genérica (sem dono) conta para o jogador 1, que é a mesma convenção do `ui/menu-nav`: quem
|
|
375
|
+
// carrega numa tecla que não é de assento nenhum está a jogar no primeiro assento.
|
|
376
|
+
if (origem) {
|
|
377
|
+
const dono = ctx.whichPlayer(code);
|
|
378
|
+
ctx.arestaDoJogador(dono < 0 ? 0 : dono, origem);
|
|
379
|
+
}
|
|
371
380
|
return;
|
|
372
381
|
}
|
|
373
382
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
import { type JogadorDaAlternancia } from './latch-sync.js';
|
|
3
|
+
import type { ArmazemDaAlternancia } from './latch-store.js';
|
|
4
|
+
import type { Transporte } from './transporte-em-uso.js';
|
|
5
|
+
export interface ArestaComAlternanciaOpts {
|
|
6
|
+
/**
|
|
7
|
+
* O armazenamento. Injectável **para o gate**, e com padrão para o consumidor não poder esquecê-lo.
|
|
8
|
+
*
|
|
9
|
+
* ⚠️ Padrão e não campo obrigatório, e a razão é a mesma do `ui/pause-icons`: um armazém injectado é uma
|
|
10
|
+
* coisa que um cartucho pode omitir, e omiti-la faria a criança perder a escolha guardada — em silêncio, e
|
|
11
|
+
* só naquele jogo.
|
|
12
|
+
*/
|
|
13
|
+
readonly armazem?: ArmazemDaAlternancia;
|
|
14
|
+
/** O padrão de fábrica. `DEFAULTS.toggleMove`, e não `false` escrito à mão: há UMA fonte (ADR-0029). */
|
|
15
|
+
readonly padrao?: boolean;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* DEVOLVE O `arestaDoJogador` QUE TAMBÉM RESOLVE A ALTERNÂNCIA — para passar a `initKeydown` e a
|
|
19
|
+
* `initTouchBindings` no lugar do cru.
|
|
20
|
+
*
|
|
21
|
+
* ⚠️ RESOLVE CONTRA `entradaDe(jogador).emUso` E NÃO CONTRA `origem`, e a distinção é de desenho e não de
|
|
22
|
+
* comportamento: hoje o `aposAresta` põe sempre `emUso = origem`, logo trocar uma pela outra é uma mutação
|
|
23
|
+
* EQUIVALENTE — está registada como tal no gate, em vez de fingir cobertura. O que a escolha compra é o
|
|
24
|
+
* futuro: quem decide que aparelho está em uso é o autómato, e o dia em que ele ganhar uma regra que RECUSE
|
|
25
|
+
* uma aresta (um falso positivo da webcam a ser filtrado, por exemplo) esta linha segue-o sem ser editada.
|
|
26
|
+
* Ler `origem` seria uma segunda resposta à pergunta que o `input/transporte-em-uso` existe para responder.
|
|
27
|
+
*/
|
|
28
|
+
export declare function criarArestaComAlternancia(getPlayers: () => readonly (JogadorDaAlternancia | null | undefined)[], opts?: ArestaComAlternanciaOpts): (jogador: number, origem: Transporte) => void;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
// input/latch-edge.ts — A ARESTA E A ALTERNÂNCIA, NUMA FUNÇÃO SÓ (ADR-0113, issue #127).
|
|
3
|
+
//
|
|
4
|
+
// ========================= POR QUE O PAR NÃO PODE SEPARAR-SE =========================
|
|
5
|
+
// Registar de que aparelho veio a aresta e resolver a alternância desse aparelho são duas metades de UM
|
|
6
|
+
// acontecimento: a criança mudou de controle. Feitas em sítios diferentes, a segunda pode faltar — e o
|
|
7
|
+
// resultado é a forma de defeito que este projecto já pagou várias vezes: o autómato sabe que ela pegou no
|
|
8
|
+
// controle, e o jogo continua a andar com a alternância do teclado. Sem erro, e só ela dá por isso.
|
|
9
|
+
//
|
|
10
|
+
// 📌 É o mesmo movimento do `consumir` no `ui/menu-nav` («uma função só para o par nunca se separar») e da
|
|
11
|
+
// escrita dupla no `ui/settings-motor`.
|
|
12
|
+
//
|
|
13
|
+
// ⚠️ E É UMA FÁBRICA, NÃO UM CAMPO NOVO NO CONTEXTO DE CADA MÓDULO DE ENTRADA. O `input/keydown` e o
|
|
14
|
+
// `input/touch-bindings` já recebem `arestaDoJogador(jogador, origem)`; esta função devolve uma com essa
|
|
15
|
+
// mesma assinatura, e por isso a fiação passa a estar certa sem nenhum dos dois saber que a alternância
|
|
16
|
+
// existe. Um segundo campo obrigatório em dois contextos seria mais superfície pública, mais uma coisa que um
|
|
17
|
+
// cartucho pode esquecer, e a mesma pergunta feita duas vezes.
|
|
18
|
+
import * as store from '../platform/storage.js';
|
|
19
|
+
import { DEFAULTS } from '../core/state.js';
|
|
20
|
+
import { arestaDoJogador, entradaDe } from './state.js';
|
|
21
|
+
import { sincronizarAlternancia } from './latch-sync.js';
|
|
22
|
+
/**
|
|
23
|
+
* DEVOLVE O `arestaDoJogador` QUE TAMBÉM RESOLVE A ALTERNÂNCIA — para passar a `initKeydown` e a
|
|
24
|
+
* `initTouchBindings` no lugar do cru.
|
|
25
|
+
*
|
|
26
|
+
* ⚠️ RESOLVE CONTRA `entradaDe(jogador).emUso` E NÃO CONTRA `origem`, e a distinção é de desenho e não de
|
|
27
|
+
* comportamento: hoje o `aposAresta` põe sempre `emUso = origem`, logo trocar uma pela outra é uma mutação
|
|
28
|
+
* EQUIVALENTE — está registada como tal no gate, em vez de fingir cobertura. O que a escolha compra é o
|
|
29
|
+
* futuro: quem decide que aparelho está em uso é o autómato, e o dia em que ele ganhar uma regra que RECUSE
|
|
30
|
+
* uma aresta (um falso positivo da webcam a ser filtrado, por exemplo) esta linha segue-o sem ser editada.
|
|
31
|
+
* Ler `origem` seria uma segunda resposta à pergunta que o `input/transporte-em-uso` existe para responder.
|
|
32
|
+
*/
|
|
33
|
+
export function criarArestaComAlternancia(getPlayers, opts = {}) {
|
|
34
|
+
const armazem = opts.armazem ?? store;
|
|
35
|
+
const padrao = opts.padrao ?? DEFAULTS.toggleMove;
|
|
36
|
+
return (jogador, origem) => {
|
|
37
|
+
arestaDoJogador(jogador, origem);
|
|
38
|
+
// 📌 O JOGADOR PODE NÃO EXISTIR — uma tela em espera, um assento que ainda não entrou —, e isso não torna
|
|
39
|
+
// a aresta inválida: o transporte em uso é facto sobre a ENTRADA e fica registado à mesma. O que não
|
|
40
|
+
// acontece é a segunda metade, porque não há onde a escrever.
|
|
41
|
+
const p = getPlayers()[jogador];
|
|
42
|
+
if (p)
|
|
43
|
+
sincronizarAlternancia(p, armazem, jogador, entradaDe(jogador).emUso, padrao);
|
|
44
|
+
};
|
|
45
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
import type { PlayerView } from '../core/entity.js';
|
|
3
|
+
import { type ArmazemDaAlternancia } from './latch-store.js';
|
|
4
|
+
/**
|
|
5
|
+
* O MÍNIMO DO JOGADOR que a alternância toca — dois campos, e nenhum deles é do contrato do jogo.
|
|
6
|
+
*
|
|
7
|
+
* 📌 `PlayerView` e não `PlayerBase`: este módulo não tem nada que fazer com sprites, física ou câmara, e um
|
|
8
|
+
* tipo largo aqui faria um gate precisar de um jogador inteiro de mentira para afirmar duas linhas.
|
|
9
|
+
*
|
|
10
|
+
* ⚠️ E ELE MUDOU DE CASA EM VEZ DE NASCER SEGUNDO. Esta linha existia, palavra por palavra, no
|
|
11
|
+
* `ui/settings-motor` — e escrevê-la aqui outra vez seria a segunda cópia de um tipo, que é o defeito que
|
|
12
|
+
* este repositório já pagou dezasseis vezes com o `DomQuery`. O painel passou a publicá-la por ALIAS, para o
|
|
13
|
+
* retrato de nomes não a ler como removida.
|
|
14
|
+
*/
|
|
15
|
+
export type JogadorDaAlternancia = PlayerView<'toggleMove' | 'walkDir'>;
|
|
16
|
+
/**
|
|
17
|
+
* A base com que a alternância de MARCHA vive no armazenamento da criança.
|
|
18
|
+
*
|
|
19
|
+
* ⚠️ A IRMÃ (`togglerun`, a alternância de CORRER) NÃO ENTRA AQUI HOJE, e a ausência é declarada em vez de
|
|
20
|
+
* esquecida: `p.toggleRun` tem um leitor de RODADA no cartucho (`game/run-toggle`), com uma trava própria que
|
|
21
|
+
* diz se está a correr AGORA — o `walkDir = 0` daqui não é o gesto certo para ela, e inventar-lhe um sem o
|
|
22
|
+
* leitor à frente seria decidir por um jogo que não abri. O `input/latch-store` já aceita a base como
|
|
23
|
+
* argumento, então quando ela entrar entra sem uma segunda forma da mesma pergunta.
|
|
24
|
+
*/
|
|
25
|
+
export declare const BASE_DA_MARCHA = "togglemove";
|
|
26
|
+
/**
|
|
27
|
+
* PÕE A ALTERNÂNCIA DE MARCHA NO JOGADOR, com a regra que a acompanha. Devolve se MUDOU alguma coisa.
|
|
28
|
+
*
|
|
29
|
+
* ⚠️ O `walkDir = 0` só corre quando a alternância CAI. Zerá-lo em toda chamada tiraria a direcção a quem
|
|
30
|
+
* está a andar, uma vez por aresta — que é o defeito ao contrário, e mais frequente.
|
|
31
|
+
*
|
|
32
|
+
* 📌 Devolver «mudou» não é conveniência: quem chama na aresta corre isto muitas vezes por segundo, e anunciar
|
|
33
|
+
* ou reflectir a cada chamada encheria o leitor de tela com a mesma frase.
|
|
34
|
+
*/
|
|
35
|
+
export declare function aplicarAlternancia(p: JogadorDaAlternancia, ligada: boolean): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* A ALTERNÂNCIA DESTE JOGADOR, RESOLVIDA PARA O TRANSPORTE EM USO E ESCRITA NELE. Devolve se mudou.
|
|
38
|
+
*
|
|
39
|
+
* É a cláusula 1 do ADR-0113 em código, e a propriedade que ela promete é NEGATIVA: chamar isto ao trocar de
|
|
40
|
+
* aparelho troca a resposta **sem escrever no armazenamento**. Um `sincronizar` que gravasse o valor resolvido
|
|
41
|
+
* apagaria, na primeira aresta, a escolha que a criança fez no outro controle.
|
|
42
|
+
*
|
|
43
|
+
* ⚠️ E NOS QUATRO ASSISTIDOS ELE RESPONDE `true` SEM CONSULTAR NADA — a regra vive no `latch-scope` e a razão
|
|
44
|
+
* está lá: em olhos, rosto, gestos e fala a alternância é o que faz a entrada funcionar, e herdar um `false`
|
|
45
|
+
* que a criança escolheu no teclado deixá-la-ia com um controle de olhar que não responde.
|
|
46
|
+
*/
|
|
47
|
+
export declare function sincronizarAlternancia(p: JogadorDaAlternancia, armazem: ArmazemDaAlternancia, jogador: number, transporte: string, padrao: boolean): boolean;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
import { alternanciaGuardada } from './latch-store.js';
|
|
3
|
+
/**
|
|
4
|
+
* A base com que a alternância de MARCHA vive no armazenamento da criança.
|
|
5
|
+
*
|
|
6
|
+
* ⚠️ A IRMÃ (`togglerun`, a alternância de CORRER) NÃO ENTRA AQUI HOJE, e a ausência é declarada em vez de
|
|
7
|
+
* esquecida: `p.toggleRun` tem um leitor de RODADA no cartucho (`game/run-toggle`), com uma trava própria que
|
|
8
|
+
* diz se está a correr AGORA — o `walkDir = 0` daqui não é o gesto certo para ela, e inventar-lhe um sem o
|
|
9
|
+
* leitor à frente seria decidir por um jogo que não abri. O `input/latch-store` já aceita a base como
|
|
10
|
+
* argumento, então quando ela entrar entra sem uma segunda forma da mesma pergunta.
|
|
11
|
+
*/
|
|
12
|
+
export const BASE_DA_MARCHA = 'togglemove';
|
|
13
|
+
/**
|
|
14
|
+
* PÕE A ALTERNÂNCIA DE MARCHA NO JOGADOR, com a regra que a acompanha. Devolve se MUDOU alguma coisa.
|
|
15
|
+
*
|
|
16
|
+
* ⚠️ O `walkDir = 0` só corre quando a alternância CAI. Zerá-lo em toda chamada tiraria a direcção a quem
|
|
17
|
+
* está a andar, uma vez por aresta — que é o defeito ao contrário, e mais frequente.
|
|
18
|
+
*
|
|
19
|
+
* 📌 Devolver «mudou» não é conveniência: quem chama na aresta corre isto muitas vezes por segundo, e anunciar
|
|
20
|
+
* ou reflectir a cada chamada encheria o leitor de tela com a mesma frase.
|
|
21
|
+
*/
|
|
22
|
+
export function aplicarAlternancia(p, ligada) {
|
|
23
|
+
if (p.toggleMove === ligada)
|
|
24
|
+
return false;
|
|
25
|
+
p.toggleMove = ligada;
|
|
26
|
+
if (!ligada)
|
|
27
|
+
p.walkDir = 0;
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* A ALTERNÂNCIA DESTE JOGADOR, RESOLVIDA PARA O TRANSPORTE EM USO E ESCRITA NELE. Devolve se mudou.
|
|
32
|
+
*
|
|
33
|
+
* É a cláusula 1 do ADR-0113 em código, e a propriedade que ela promete é NEGATIVA: chamar isto ao trocar de
|
|
34
|
+
* aparelho troca a resposta **sem escrever no armazenamento**. Um `sincronizar` que gravasse o valor resolvido
|
|
35
|
+
* apagaria, na primeira aresta, a escolha que a criança fez no outro controle.
|
|
36
|
+
*
|
|
37
|
+
* ⚠️ E NOS QUATRO ASSISTIDOS ELE RESPONDE `true` SEM CONSULTAR NADA — a regra vive no `latch-scope` e a razão
|
|
38
|
+
* está lá: em olhos, rosto, gestos e fala a alternância é o que faz a entrada funcionar, e herdar um `false`
|
|
39
|
+
* que a criança escolheu no teclado deixá-la-ia com um controle de olhar que não responde.
|
|
40
|
+
*/
|
|
41
|
+
export function sincronizarAlternancia(p, armazem, jogador, transporte, padrao) {
|
|
42
|
+
return aplicarAlternancia(p, alternanciaGuardada(armazem, BASE_DA_MARCHA, jogador, transporte, padrao));
|
|
43
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
import type { Action } from '../core/actions.js';
|
|
3
|
+
import { type Binding } from './default-bindings.js';
|
|
4
|
+
/** O que o jogo declara: só o que ele quer mudar. `null` num botão é «esta posição não existe neste jogo». */
|
|
5
|
+
export type MapeamentoDoPad = (jogadores: number, assento: number) => Partial<Record<Action, number | null>> | null;
|
|
6
|
+
export type TabelaDoPad = Readonly<Record<Action, Binding<number>>>;
|
|
7
|
+
/**
|
|
8
|
+
* REGISTA O PADRÃO DO JOGO. Chamado uma vez pelo arranque; `null` limpa (é o que um jogo sem opinião produz).
|
|
9
|
+
*
|
|
10
|
+
* ⚠️ LIMPA A MEMÓRIA, e sem esta linha o registo seria pior do que não existir: uma segunda montagem — outro
|
|
11
|
+
* jogo na mesma página, um teste a seguir a outro — leria a tabela do jogo anterior, e a leitura estaria
|
|
12
|
+
* certa em toda parte menos no valor.
|
|
13
|
+
*/
|
|
14
|
+
export declare function registrarMapeamentoDoPad(f: MapeamentoDoPad | null): void;
|
|
15
|
+
/**
|
|
16
|
+
* A TABELA DE BOTÕES PARA ESTE ARRANJO E ESTE ASSENTO — fábrica da engine com o padrão do jogo por cima.
|
|
17
|
+
*
|
|
18
|
+
* 📌 MEMOIZADA porque isto é lido no laço de sondagem, uma vez por controle e por quadro: fundir dois objectos
|
|
19
|
+
* sessenta vezes por segundo por jogador é lixo que nenhuma criança vê e que o coletor paga. A chave é
|
|
20
|
+
* `arranjo:assento`, e o registo limpa-a — que é o único momento em que a resposta pode mudar.
|
|
21
|
+
*/
|
|
22
|
+
export declare function tabelaDoPad(jogadores: number, assento: number): TabelaDoPad;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
import { GAMEPAD_STANDARD } from './default-bindings.js';
|
|
3
|
+
let mapeamentoDoJogo = null;
|
|
4
|
+
const memo = new Map();
|
|
5
|
+
/**
|
|
6
|
+
* REGISTA O PADRÃO DO JOGO. Chamado uma vez pelo arranque; `null` limpa (é o que um jogo sem opinião produz).
|
|
7
|
+
*
|
|
8
|
+
* ⚠️ LIMPA A MEMÓRIA, e sem esta linha o registo seria pior do que não existir: uma segunda montagem — outro
|
|
9
|
+
* jogo na mesma página, um teste a seguir a outro — leria a tabela do jogo anterior, e a leitura estaria
|
|
10
|
+
* certa em toda parte menos no valor.
|
|
11
|
+
*/
|
|
12
|
+
export function registrarMapeamentoDoPad(f) {
|
|
13
|
+
mapeamentoDoJogo = f;
|
|
14
|
+
memo.clear();
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* A TABELA DE BOTÕES PARA ESTE ARRANJO E ESTE ASSENTO — fábrica da engine com o padrão do jogo por cima.
|
|
18
|
+
*
|
|
19
|
+
* 📌 MEMOIZADA porque isto é lido no laço de sondagem, uma vez por controle e por quadro: fundir dois objectos
|
|
20
|
+
* sessenta vezes por segundo por jogador é lixo que nenhuma criança vê e que o coletor paga. A chave é
|
|
21
|
+
* `arranjo:assento`, e o registo limpa-a — que é o único momento em que a resposta pode mudar.
|
|
22
|
+
*/
|
|
23
|
+
export function tabelaDoPad(jogadores, assento) {
|
|
24
|
+
if (!mapeamentoDoJogo)
|
|
25
|
+
return GAMEPAD_STANDARD;
|
|
26
|
+
const chave = `${jogadores}:${assento}`;
|
|
27
|
+
const guardada = memo.get(chave);
|
|
28
|
+
if (guardada)
|
|
29
|
+
return guardada;
|
|
30
|
+
const parcial = mapeamentoDoJogo(jogadores, assento);
|
|
31
|
+
const tabela = parcial ? Object.freeze({ ...GAMEPAD_STANDARD, ...parcial }) : GAMEPAD_STANDARD;
|
|
32
|
+
memo.set(chave, tabela);
|
|
33
|
+
return tabela;
|
|
34
|
+
}
|
|
@@ -174,6 +174,16 @@ export interface TouchBindingsCtx {
|
|
|
174
174
|
/** o array vivo de jogadores. Getter: o main.js o repovoa a cada `restartGame`. */
|
|
175
175
|
getPlayers: () => readonly TouchBindPlayer[];
|
|
176
176
|
marcarTecla: (code: string, origem: Transporte) => void;
|
|
177
|
+
/**
|
|
178
|
+
* ESTA ARESTA É DESTE JOGADOR, E VEIO DO TOQUE (ADR-0113 cláusula 4, issue #127) —
|
|
179
|
+
* `input/state.arestaDoJogador`.
|
|
180
|
+
*
|
|
181
|
+
* 🔴 OBRIGATÓRIO, e é aqui que a troca de aparelho fica VISÍVEL: o toque é o transporte que a criança usa
|
|
182
|
+
* ao lado do teclado, e sem esta linha o autómato responde `teclado` mesmo com o dedo no ecrã — logo a
|
|
183
|
+
* alternância lida seria a do teclado, no aparelho errado. 📌 O `onTouchControlsShown` do cartucho
|
|
184
|
+
* (`main.ts:1695`) é o remendo que existe hoje exactamente para compensar esta falta.
|
|
185
|
+
*/
|
|
186
|
+
arestaDoJogador: (jogador: number, origem: Transporte) => void;
|
|
177
187
|
soltarTecla: (code: string) => void;
|
|
178
188
|
/**
|
|
179
189
|
* O conjunto para LER — a decisão pura pergunta que teclas já estão seguradas.
|
|
@@ -236,6 +236,12 @@ export function initTouchBindings(ctx) {
|
|
|
236
236
|
const p = players[playerIndex];
|
|
237
237
|
if (p)
|
|
238
238
|
p[edge] = true;
|
|
239
|
+
// 📌 A ARESTA POR JOGADOR, ao lado da borda que ela levanta — e não uma vez por toque: o mesmo código
|
|
240
|
+
// pode pertencer a mais de um assento (`d.edges` é construído com `includes` sobre o esquema de cada
|
|
241
|
+
// um), e o transporte em uso é uma pergunta POR CRIANÇA. Marcar só o jogador 0 daria a alternância do
|
|
242
|
+
// primeiro assento a quem joga no segundo.
|
|
243
|
+
if (p)
|
|
244
|
+
ctx.arestaDoJogador(playerIndex, 'toque');
|
|
239
245
|
}
|
|
240
246
|
}
|
|
241
247
|
if (d.hideTips)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
/** Uma coisa pesada que a engine promete e que não cabe no pacote. */
|
|
3
|
+
export interface Pesado {
|
|
4
|
+
readonly id: string;
|
|
5
|
+
/** `null` = decidido que existe, mas ainda não há de onde vir. Ver `porQueNaoTemFonte`. */
|
|
6
|
+
readonly url: string | null;
|
|
7
|
+
/** Medido, não estimado — é o número que uma frase honesta usa antes de começar a descarga. */
|
|
8
|
+
readonly bytes?: number;
|
|
9
|
+
/** Obrigatório quando `url` é `null`: uma ausência sem razão escrita vira uma ausência esquecida. */
|
|
10
|
+
readonly porQueNaoTemFonte?: string;
|
|
11
|
+
}
|
|
12
|
+
/** O nome da Cache Storage. Versionado: mudar o conteúdo do catálogo não deve servir bytes velhos. */
|
|
13
|
+
export declare const CACHE_PESADOS = "incl-pesados-v1";
|
|
14
|
+
export declare const PESADOS: readonly Pesado[];
|