Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .github/workflows/pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ name: GitHub Pages
on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch:
permissions:
contents: read
Expand Down Expand Up @@ -50,11 +52,20 @@ jobs:
if curl --fail --silent "$TEST_URL" > /dev/null; then break; fi
sleep 1
done
curl --fail --silent "$TEST_URL" > /dev/null
npm run test:e2e
- name: Save browser failure evidence
if: failure()
uses: actions/upload-artifact@v4
with:
name: browser-test-results
path: test-results/
if-no-files-found: ignore
- uses: actions/upload-pages-artifact@v3
with:
path: dist
deploy:
if: github.ref == 'refs/heads/main'
needs: build
runs-on: ubuntu-latest
permissions:
Expand Down
67 changes: 67 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Dancer

Editor de danças Habbo em AstroJS, TypeScript e [WiredSnippets/wsproom](https://github.com/WiredSnippets/wsproom). Site estático: a edição, reprodução e busca de usuários acontecem no navegador.

## Executar

Requer Node.js 22 e Git. No PowerShell com scripts desabilitados, use `npm.cmd` em lugar de `npm`.

```sh
npm ci
npm run assets:prepare
npm run dev
```

A primeira preparação baixa e converte as bibliotecas de avatar com as ferramentas do wsproom. Pode demorar vários minutos. Não baixa furnis. Aguarde a preparação terminar antes de iniciar o servidor de desenvolvimento.

Os downloads ficam em `.cache/shroom/`; os arquivos publicados em `public/assets/shroom/`. Ambos são ignorados pelo Git. As quatro danças da raiz são exemplos fornecidos com o projeto e permanecem versionadas.

```sh
npm run assets:check
npm test
npm run typecheck
npm run build
npm run preview
```

Com o servidor iniciado, execute `npm run test:e2e` para os testes de navegador. No Windows eles usam o Edge instalado; em Linux execute antes `npx playwright install --with-deps chromium`. `TEST_URL` define outra URL, incluindo o subdiretório de publicação.

O hook de build do Astro valida hashes, XML, bibliotecas e imagens. Assets ausentes, incompletos ou alterados impedem o build, inclusive ao executar `astro build` diretamente. Os assets são incluídos no artefato estático `dist/`, sem serem commitados.

Para atualizar o catálogo: `npm run assets:prepare -- --refresh`. A variável `HABBO_EXTERNAL_VARIABLES` permite escolher outra configuração pública de assets. A preparação reutiliza SWFs já baixados da mesma versão do catálogo.

## Usar

- Abra uma das quatro danças ou importe XML, `.shroom` ou `.wsproom`.
- Selecione um frame e altere ação, frame do sprite, `dx`, `dy` e `dd` de cada parte.
- Adicione, duplique, remova ou reordene frames. A prévia reflete as edições.
- Use play/pause, o seletor de frame e as setas de rotação. Espaço também alterna a reprodução quando o foco está fora dos campos.
- Cole uma figurestring ou selecione Usuário, informe o nick e escolha o hotel.
- Exporte em XML ou SHROOM. O rascunho também é salvo neste navegador quando o armazenamento local está disponível.

A busca usa diretamente `https://www.habbo.[hotel]/api/public/users?name=<nick>` e lê `figureString`. Depende da disponibilidade e política CORS do hotel. A edição com figurestring continua disponível quando a consulta falha.

## GitHub Pages

1. Envie o projeto para seu repositório GitHub, branch `main`.
2. Em **Settings → Pages → Build and deployment**, escolha **GitHub Actions**.
3. Execute o workflow **GitHub Pages** ou envie um commit para `main`.

O workflow instala dependências pelo lockfile, prepara os assets, executa testes, a checagem obrigatória do build e testes de navegador no resultado estático, e publica o artefato. `site` e `base` são calculados pelo nome do repositório. Não é preciso commitar assets nem criar branch `gh-pages`.

Localmente, `SITE_URL` e `BASE_PATH` permitem reproduzir a URL de publicação. Exemplo PowerShell:

```powershell
$env:SITE_URL = 'https://seu-usuario.github.io'
$env:BASE_PATH = '/dancer/'
npm run build
npm run preview
```

## Motor e assets

O motor é `@wiredsnippets/shroom@1.1.0`, com ferramentas de conversão da revisão `eaf266f54d5c8a9eb06174f13a85174e2745e034` de WiredSnippets/wsproom. O adaptador de edição limpa apenas os caches de definição de animação, preservando bibliotecas e texturas; essa integração deve ser revisada ao atualizar o motor.

Alguns SWFs oficiais contêm entradas de manifest sem símbolo correspondente. A preparação remove apenas referências comprovadamente ausentes no SWF original, mantendo a checagem de falhas de extração.

Shroom é distribuído sob **LGPL-3.0-or-later**; consulte [COPYING.LESSER](https://github.com/WiredSnippets/wsproom/blob/master/COPYING.LESSER). Os assets Habbo pertencem aos respectivos titulares e não integram o código-fonte deste repositório.
72 changes: 38 additions & 34 deletions docs/superpowers/plans/2026-09-20-dancer.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,66 +34,70 @@

**Interfaces:** `parseDance(input: Uint8Array | string): DanceDocument`; `toXml(document: DanceDocument): string`; `toShroom(document: DanceDocument): Uint8Array`. Documento contém nome, descrição e frames com partes identificadas por id e atributos action/frame/dx/dy/dd; preservar atributos extras suportados.

- [ ] Criar teste parametrizado com Dance1–4: importar, conferir contagens `[8,8,10,16]`, exportar e reimportar, comparando estrutura e valores negativos.
- [ ] Testar truncamento do container, comprimentos fora dos limites, XML malformado e ausência de frames; executar teste e registrar falha antes da implementação.
- [ ] Implementar codec seguindo o formato de `ShroomAssetBundle` upstream, sem tratar bytes binários como texto integral.
- [ ] Implementar criação, duplicação, remoção e reordenação com frame ativo sempre válido; testar que o último frame não é removido.
- [ ] Executar testes e commitar `feat: add dance document and SHROOM codecs`.
- [x] Criar teste parametrizado com Dance1–4: importar, conferir contagens `[8,8,10,16]`, exportar e reimportar, comparando estrutura e valores negativos.
- [x] Testar truncamento do container, comprimentos fora dos limites, XML malformado e ausência de frames; executar teste e registrar falha antes da implementação.
- [x] Implementar codec seguindo o formato de `ShroomAssetBundle` upstream, sem tratar bytes binários como texto integral.
- [x] Implementar criação, duplicação, remoção e reordenação com frame ativo sempre válido; testar que o último frame não é removido.
- [x] Executar testes e commitar `feat: add dance document and SHROOM codecs`.

## 2. Astro e pipeline de assets

**Arquivos:** `astro.config.mjs`, `scripts/prepare-assets.ts`, `scripts/check-assets.ts`, `scripts/asset-inventory.ts`, `integrations/required-assets.mjs`, `tests/assets.test.ts`, `src/pages/index.astro`.

**Interfaces:** preparação produz metadados XML e bibliotecas wsproom em `public/assets/shroom/`; `checkAssets(root: string): Promise<void>` lança erro descritivo ao encontrar ausência ou corrupção.

- [ ] Fixar versão/revisão do wsproom e versões compatíveis de Astro/PixiJS após verificar requisitos de Node. Gerar lockfile.
- [ ] Testar fixtures de assets ausentes, vazios, XML inválido e biblioteca referenciada ausente. Uma pasta vazia deve falhar.
- [ ] Compor download de figuras e conversão upstream individualmente; excluir fluxo genérico que baixa furnis. Validar status HTTP, concluir inventário somente após download e conversão completos.
- [ ] Checar arquivos referenciados pelo figuremap e manifests, incluindo arquivos internos das bibliotecas. Associar inventário à revisão do motor e à origem dos dados.
- [ ] Adicionar `assets:prepare`, `assets:check`, `dev`, `build` e `preview`. Um hook `astro:build:start` aguarda `checkAssets`; falha impede emissão do site.
- [ ] Configurar `output: 'static'`, `site` e `base` por ambiente; buscar arquivos no cliente com `import.meta.env.BASE_URL`.
- [ ] Executar build sem assets e confirmar falha; preparar assets reais e confirmar checagem positiva. Conferir `git ls-files public/assets/shroom .cache/shroom` vazio.
- [ ] Commit `build: configure Astro and mandatory Shroom assets`.
- [x] Fixar versão/revisão do wsproom e versões compatíveis de Astro/PixiJS após verificar requisitos de Node. Gerar lockfile.
- [x] Testar fixtures de assets ausentes, vazios, XML inválido e biblioteca referenciada ausente. Uma pasta vazia deve falhar.
- [x] Compor download de figuras e conversão upstream individualmente; excluir fluxo genérico que baixa furnis. Validar status HTTP, concluir inventário somente após download e conversão completos.
- [x] Checar arquivos referenciados pelo figuremap e manifests, incluindo arquivos internos das bibliotecas. Associar inventário à revisão do motor e à origem dos dados.
- [x] Adicionar `assets:prepare`, `assets:check`, `dev`, `build` e `preview`. Um hook `astro:build:start` aguarda `checkAssets`; falha impede emissão do site.
- [x] Configurar `output: 'static'`, `site` e `base` por ambiente; buscar arquivos no cliente com `import.meta.env.BASE_URL`.
- [x] Executar build sem assets e confirmar falha; preparar assets reais e confirmar checagem positiva. Conferir `git ls-files public/assets/shroom .cache/shroom` vazio.
- [x] Commit `build: configure Astro and mandatory Shroom assets`.

## 3. Motor e reprodução

**Arquivos:** `src/preview/ticker.ts`, `src/preview/renderer.ts`, `src/preview/dance-loader.ts`, `tests/playback.test.ts`.

**Interfaces:** `Preview.setDance(document)`, `Preview.seek(index)`, `Preview.setFigure(figure)`, `Preview.setDirection(direction)`, `Preview.destroy()`. Ticker implementa `IAnimationTicker.subscribe` e `current` upstream, com avanço manual controlado.

- [ ] Testar relógio: pausa mantém frame, seek escolhe frame exato, play dá volta no último frame e elapsed time não depende da taxa de pintura.
- [ ] Injetar ticker em `Shroom`; criar quarto 3×3 sem paredes e avatar em `(1,1,0)`.
- [ ] Fornecer XML editado como dados de efeito ao AvatarLoader. Invalidar caches de efeitos/desenho em edições sem acumular bibliotecas por tecla pressionada.
- [ ] Sincronizar relógio do avatar com seek inclusive depois de carregamento assíncrono ou troca de aparência.
- [ ] Verificar no navegador cada preset, deslocamentos negativos e `dd`, pausa/seek e oito direções. Garantir liberação de ticker, texturas e listeners no descarte.
- [ ] Commit `feat: render editable dances with deterministic playback`.
- [x] Testar relógio: pausa mantém frame, seek escolhe frame exato, play dá volta no último frame e elapsed time não depende da taxa de pintura.
- [x] Injetar ticker em `Shroom`; criar quarto 3×3 sem paredes e avatar em `(1,1,0)`.
- [x] Fornecer XML editado como dados de efeito ao AvatarLoader. Invalidar caches de efeitos/desenho em edições sem acumular bibliotecas por tecla pressionada.
- [x] Sincronizar relógio do avatar com seek inclusive depois de carregamento assíncrono ou troca de aparência.
- [x] Verificar no navegador cada preset, deslocamentos negativos e `dd`, pausa/seek e oito direções. Garantir liberação de ticker, texturas e listeners no descarte.
- [x] Commit `feat: render editable dances with deterministic playback`.

## 4. Editor e aparência

**Arquivos:** `src/editor/controller.ts`, `src/editor/view.ts`, `src/editor/storage.ts`, `src/avatar/hotels.ts`, `src/avatar/lookup.ts`, `src/styles/editor.css`, `tests/lookup.test.ts`, `tests/editor.test.ts`.

**Interfaces:** `lookupFigure(hotel: Hotel, nick: string, signal?: AbortSignal): Promise<string>`; estado único contém documento, frame ativo, reprodução, figurestring e direção.

- [ ] Testar URL com `URLSearchParams`, hotel inválido, 404, timeout, payload sem figureString e cancelamento. Impedir respostas obsoletas de substituir aparência atual.
- [ ] Construir controles compactos para presets, importação/exportação, frames e tabela de partes. Prévia adjacente com play/pause, rotação e range rotulado.
- [ ] Aplicar figurestring diretamente ou obter `figureString` pela API solicitada. Mostrar erro curto preservando o avatar anterior.
- [ ] Pausar ao selecionar frame; aplicar edições instantaneamente. Implementar persistência local com tratamento de armazenamento indisponível e dados inválidos.
- [ ] Testar falha de importação preservando documento, exclusão do frame ativo ajustando índice e recuperação de rascunho.
- [ ] Inspecionar visualmente desktop e tela estreita; verificar navegação por teclado e rótulos acessíveis, sem títulos decorativos.
- [ ] Commit `feat: add minimal frame editor and hotel avatar lookup`.
- [x] Testar URL com `URLSearchParams`, hotel inválido, 404, timeout, payload sem figureString e cancelamento. Impedir respostas obsoletas de substituir aparência atual.
- [x] Construir controles compactos para presets, importação/exportação, frames e tabela de partes. Prévia adjacente com play/pause, rotação e range rotulado.
- [x] Aplicar figurestring diretamente ou obter `figureString` pela API solicitada. Mostrar erro curto preservando o avatar anterior.
- [x] Pausar ao selecionar frame; aplicar edições instantaneamente. Implementar persistência local com tratamento de armazenamento indisponível e dados inválidos.
- [x] Testar falha de importação preservando documento, exclusão do frame ativo ajustando índice e recuperação de rascunho.
- [x] Inspecionar visualmente desktop e tela estreita; verificar navegação por teclado e rótulos acessíveis, sem títulos decorativos.
- [x] Commit `feat: add minimal frame editor and hotel avatar lookup`.

## 5. GitHub Pages e validação final

**Arquivos:** `.github/workflows/pages.yml`, `README.md`, `tests/e2e/editor.spec.ts`.

- [ ] Criar workflow com instalação por lockfile, preparação/cache dos assets, testes, build validado e publicação por artifact do Pages. Usar `contents: read`, `pages: write`, `id-token: write` e environment `github-pages`.
- [ ] Derivar site/base do repositório no workflow, incluindo o caso de repositório `<owner>.github.io`. Artefato contém `dist`, não fontes ou cache de SWFs.
- [ ] Testar sob `/dancer/`: carregar presets e assets, play/pause/seek, editar e exportar/reimportar, rotacionar e trocar aparência.
- [ ] Verificar requisição real à API pública no navegador; registrar eventuais bloqueios CORS ou restrições externas em vez de simular sucesso.
- [ ] Documentar comandos de instalação, assets, desenvolvimento, build e ativação do Pages, além da origem/licença do motor.
- [ ] Rodar testes, typecheck e build; conferir arquivos versionados e commits; commit `ci: add GitHub Pages deployment and usage guide`.
- [x] Criar workflow com instalação por lockfile, preparação/cache dos assets, testes, build validado e publicação por artifact do Pages. Usar `contents: read`, `pages: write`, `id-token: write` e environment `github-pages`.
- [x] Derivar site/base do repositório no workflow, incluindo o caso de repositório `<owner>.github.io`. Artefato contém `dist`, não fontes ou cache de SWFs.
- [x] Testar sob `/dancer/`: carregar presets e assets, play/pause/seek, editar e exportar/reimportar, rotacionar e trocar aparência.
- [x] Verificar requisição real à API pública no navegador; registrar eventuais bloqueios CORS ou restrições externas em vez de simular sucesso.
- [x] Documentar comandos de instalação, assets, desenvolvimento, build e ativação do Pages, além da origem/licença do motor.
- [x] Rodar testes, typecheck e build; conferir arquivos versionados e commits; commit `ci: add GitHub Pages deployment and usage guide`.
- [ ] Se houver remoto autorizado, publicar e conferir workflow e URL. Se continuar sem remoto, informar exatamente o que falta para deploy, sem afirmar publicação concluída.

## Execução proposta
## Execução e verificação

Execução nativa nesta sessão, por etapas, pois o adaptador, os assets e o editor compartilham contratos estreitos. Plano aguardando revisão e escolha do método pelo usuário, conforme a skill writing-plans.
Plano aprovado pelo usuário e executado diretamente nesta sessão, com commits progressivos e revisão independente ao final. As etapas 3 e 4 foram registradas juntas por compartilharem o fluxo de prévia. O usuário integrou as alterações em `Habbianos/dancer`; a primeira execução do Pages falhou nos testes de navegador. A correção salva o rascunho pendente em `pagehide` e verifica a inicialização assíncrona em teste unitário, sem substituir módulos compilados. O workflow também verifica pull requests e preserva traces em caso de falha.

Evidências: 18 testes unitários, typecheck, três testes de navegador repetidos duas vezes no build de produção sob `/dancer/`; build estático com 3.013 arquivos de assets validados. O teste de navegador cobre edição com comparação de pixels, pausa/seek, quatro presets, oito direções, XML exportado e reimportado, persistência, importação inválida, consulta ao hotel e viewport móvel. A API brasileira também foi consultada sem interceptação no navegador. O build sem assets falhou no hook obrigatório. `git ls-files public/assets/shroom .cache/shroom` retorna vazio.

Decisões de integração: usar ESM do wsproom para compartilhar uma única instância de PixiJS; converter o índice XML para duas unidades internas do motor; remover referências órfãs de manifests apenas quando também ausentes dos símbolos do SWF original. O adaptador permanece fixado na versão do motor testada.
4 changes: 2 additions & 2 deletions docs/superpowers/specs/2026-09-20-dancer-design.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ Buscar usuários diretamente do navegador em `https://www.habbo.[hotel]/api/publ

Configurar `site` e `base` para páginas de projeto e permitir personalização por ambiente. Workflow com checkout, instalação reproduzível, cache de assets associado à revisão do motor/configuração, download/conversão, testes, checagem obrigatória, build, upload do artefato e deploy no environment github-pages. Os assets fazem parte do artefato publicado, nunca dos commits. Não usar branch de distribuição para versionar os arquivos gerados.

Realizar commits progressivos por etapa funcional. Preparar workflow e instruções de ativação do Pages; a execução do deploy depende de um remoto GitHub acessível e configurado, que ainda não existe neste repositório local.
Realizar commits progressivos por etapa funcional. Preparar workflow e instruções de ativação do Pages; o remoto foi configurado pelo usuário como `Habbianos/dancer`.

## Alternativas consideradas

Expand All @@ -57,4 +57,4 @@ Entregar repositório Git local, commits progressivos, código, lockfile, workfl

## Estado

Revisada com as instruções do usuário sobre AstroJS, GitHub Pages, assets obrigatórios não versionados, API pública e commits progressivos. Código do produto ainda não implementado.
Implementada em AstroJS com editor e renderização no navegador, assets obrigatórios não versionados e workflow GitHub Pages. Revisão independente e testes de regressão concluídos. Alterações integradas pelo usuário em `Habbianos/dancer`. Correção da primeira execução do GitHub Actions validada localmente; publicação remota ainda pendente de verificação.
8 changes: 7 additions & 1 deletion playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,11 @@ import { defineConfig } from '@playwright/test';
export default defineConfig({
testDir: './tests/e2e',
timeout: 60000,
use: { baseURL: process.env.TEST_URL ?? 'http://127.0.0.1:4321/', viewport: { width: 1300, height: 850 }, launchOptions: process.platform === 'win32' ? { channel: 'msedge' } : {} },
use: {
baseURL: process.env.TEST_URL ?? 'http://127.0.0.1:4321/',
viewport: { width: 1300, height: 850 },
launchOptions: process.platform === 'win32' ? { channel: 'msedge' } : {},
trace: 'retain-on-failure',
screenshot: 'only-on-failure',
},
});
Loading
Loading